線性表學習筆記

  最近學習數據結構的線性表,主要是藉助教材《數據結構》(C語言版)那本。在課堂上學習的時候沒有認真聽講,唉,,,書上面的程序沒有寫過,知識瞭解大概,如今開始準備面試,數據結構是首先要拿下的基礎知識,因此開始了數據結構的再學習,下面是線性表部分,下面還會有棧、隊列、串、數組、樹、圖、排序、查找等等。程序不必定徹底正確,都是用C語言實現的書上的例子,沒有包括全部的線性表性質,但基本上實現了線性表基本操做(順序和鏈式),歡迎你們提出寶貴意見。c++

下面附上練習源碼(僅做參考)面試

  1 /**
  2  * 線性表的各類操做
  3  * 對應《數據結構(C語言版)》的教材
  4  * @author:zhaoyafei
  5  * @aime:2015-6-16
  6  */
  7 //引入必要頭文件
  8 #include <stdio.h>
  9 #include <stdlib.h>
 10 //約定的宏定義  
 11 #define TRUE 1
 12 #define FALSE 0
 13 #define OK 1
 14 #define ERROR 0
 15 #define INFEASIBLE -1
 16 #define OVERFLOW -2
 17 
 18 //初始空間分配量
 19 #define LIST_INIT_SIZE 100
 20 //空間分配的增量
 21 #define LISTINCREMENT  10
 22 //Status是函數的類型,其值是函數結果的狀態碼
 23 typedef int Status;
 24 //數據元素約定爲ElemType,能夠本身定義
 25 typedef int ElemType;
 26 
 27 //線性表的順序實現
 28 typedef struct{
 29     ElemType * elem;  //存儲空間的基地址
 30     int      lenght;  //當前的長度
 31     int      listsize;//當前分配的存儲容量
 32 }SqList;
 33 
 34 //線性表的鏈式實現
 35 typedef struct LNode{
 36     ElemType     data; //存儲數據
 37     struct LNode * next; //遞歸定義,指向下一個元素
 38 }LNode,*LinkList;//結構體類型指針
 39 
 40 //雙向鏈表的實現
 41 typedef struct DuLNode{
 42     ElemType data;
 43     struct DuLNode *prior;
 44     struct DuLNode *next;
 45 }DulNode, *DuLinkList;
 46 
 47 /*************************順序實現***************************/
 48 //構造空的線性表
 49 Status InitList(SqList &L, int lenght){
 50     if (lenght == 0) {
 51         lenght = LIST_INIT_SIZE;
 52     }
 53     L.elem = (ElemType *)malloc(lenght * sizeof(ElemType));
 54 
 55     if(!L.elem){
 56         exit(OVERFLOW);  //分配存儲空間失敗
 57     }
 58     L.lenght = 0;        //初始空表長度爲0
 59     L.listsize = lenght ;//初始存儲容量爲100
 60     return OK;
 61 }
 62 
 63 //在第i的位置插入元素e
 64 Status ListInse_Sq(SqList &L, ElemType e, int i){
 65     ElemType *p, *q;
 66     if(i < 0 || i > L.lenght){
 67         //i的值不合法
 68         return ERROR;
 69     }
 70     if (L.lenght >= L.listsize) {
 71         //空間不夠,從新分配存儲空間
 72         ElemType *newbase = (ElemType *)realloc(L.elem ,(L.listsize + LISTINCREMENT)*sizeof(ElemType));
 73         if(!newbase){
 74             return OVERFLOW;            //存儲分配失敗
 75         }
 76         L.elem = newbase;               //記錄新基值
 77         L.listsize += LISTINCREMENT;    //增長存儲容量
 78     }
 79     q = &L.elem[i];                     //獲得元素插入的位置
 80     for (p = &L.elem[L.lenght]; p >= q; --p) {
 81         *p = *(p-1);                    //把插入位置元素以後的元素日後移動
 82     }
 83     *q = e;                             //插入新元素e
 84     L.lenght +=1;
 85     return OK;
 86 }   
 87 
 88 //刪除第i位置元素,並用e返回其值
 89 Status ListDelete_sq(SqList &L, int i, ElemType &e){
 90     int *p,*q;
 91     if(i < 0 || i > L.lenght){
 92         return ERROR;  //i的值不合法
 93     }
 94     q = &L.elem[i];    //被刪除元素的位置爲i;
 95     e = *q;            //被刪除元素的值賦值給e
 96     //被刪除元素後的元素左移
 97     for (p = q; p< (L.elem + L.lenght); p++){  
 98         *p = *(p + 1);
 99     }
100     --L.lenght;
101     return OK;
102 }  
103 
104 //獲得第i個元素
105 Status GetElem(SqList &L, int i, ElemType &e){
106     ElemType *p;
107     p = L.elem;
108     int j = 1;
109     if(i < 1){
110         exit(OVERFLOW);//下表不合法
111     }
112     while(p && j < i){
113         p = &L.elem[j];
114         j++; //尋找第i個元素,同時檢查p是否越界
115     }
116     if(!p || j > i){
117         return false;//下標越界
118     }
119     e = L.elem[j-1];
120     return OK;
121 }
122 
123 //打印線性表
124 void PrintList(SqList L){
125     for(int i = 0; i < L.lenght; i++) {
126         printf("%d ", *(L.elem + i));
127     }
128     printf("\r\n");
129 } 
130 
131 //合併兩個線性表
132 void Combine(SqList La, SqList Lb, SqList &Lc){
133     ElemType *pa, *pb, *pc;
134     Lc.listsize =  La.lenght + Lb.lenght;
135     InitList(Lc, Lc.listsize); //初始化LC\pc = Lc.elem;
136     Lc.lenght = Lc.listsize;
137     pc = Lc.elem;
138     pa = La.elem;
139     pb = Lb.elem;
140     //尚未循環完
141     while (pa <= &La.elem[La.lenght -1] && pb <= &Lb.elem[Lb.lenght -1]){
142         if (*pa <= *pb){
143             *pc++ = *pa++;
144         }else{
145             *pc++ = *pb++;
146         }
147     }
148     //插入La的剩餘元素  
149     while(pa <= &La.elem[La.lenght -1]){
150         *pc++ = *pa++;
151     }
152     //插入Lb的剩餘元素 
153     while(pb <= &Lb.elem[Lb.lenght -1]){
154         *pc++ = *pb++;
155     }
156 } 
157 
158 //冒泡排序法,排序線性表
159 void Sort(SqList &L){
160     ElemType *pd1,*pd2,nums,length = L.lenght;
161     for(int num = 0; num < length - 1; num++){
162         for(int num1 = num + 1 ;num1 < length; num1++){
163             pd1 = &L.elem[num];
164             pd2 = &L.elem[num1];
165             if(*pd1 > *pd2){
166                 nums = *pd1;
167                 *pd1 = *pd2;
168                 *pd2 = nums;
169             }
170         }
171     }
172 }
173  
174 /*************************鏈式實現***************************/
175 //單鏈表初始化
176 Status InitList_L(LinkList &L){
177     L = (LinkList)malloc(sizeof(LNode));
178     if(!L){
179         exit(OVERFLOW);  //分配存儲空間失敗
180     }
181     L->next = NULL; //初始的頭結點爲空
182     return OK;
183 }
184 
185 //逆向創建單鏈表
186 Status CreateList_L(LinkList &L, int n){
187     L = (LinkList)malloc(sizeof(LNode));
188     if(!L){
189         exit(OVERFLOW);  //分配存儲空間失敗
190     }
191     L->next = NULL; //初始的頭結點爲空
192     printf("請輸入5個整數:\n");
193     for(int i = n; i > 0; --i){
194         LinkList p;
195         p = (LinkList)malloc(sizeof(LNode));
196         scanf("%d",&p->data);
197         p->next = L->next;
198         L->next = p;
199     }
200     return OK;
201 }
202 
203 //在創建好的單鏈表中的第n個位置插入元素e
204 Status ListInsert_L(LinkList &o, int n, ElemType e){
205     LinkList L = o;
206     int j = 0;//記錄插入點的位置
207     while(L && j < n - 1 && n > 0){
208         L = L->next;
209         j++;
210     }
211     if(L){//合法
212         LinkList p;
213         p = (LinkList)malloc(sizeof(LNode));
214         p->data = e;
215         p->next = L->next;
216         L->next = p;
217         return OK;
218     }
219 }
220 
221 //在創建好的單鏈表中的第n個位置刪除元素,並用e返回
222 Status ListDelete_L(LinkList &o, int n, ElemType e){
223     LinkList L = o;
224     int j = 0; //記錄插入點的位置
225     while(L && j < n - 1 && n > 0){
226         L = L->next;
227         j++;
228     }
229     if(L && L->next){//合法
230         LinkList q;
231         q = L->next;
232         e = q->data;
233         L->next = q->next;
234         free(q);
235         return OK;
236     }
237 }
238 
239 //合併鏈式線性表
240 void Combine_L(LinkList &La, LinkList &Lb,LinkList &Lc){
241     LinkList pa,pb,pc;
242     pa = La->next;
243     pb = Lb->next;
244     //Lc = La;//把La做爲Lc的頭結點
245     pc = Lc;
246     while(pa && pb){
247         if(pa->data <= pb->data){//判斷二者得大小
248             pc->next = pa;
249             pa = pa->next; //pa指針下移
250         }else{
251             pc->next = pb;
252             pb = pb->next; //pb指針下移
253         }
254         pc = pc->next; //pc下移一位
255     }
256     pc->next = pa ? pa : pb;
257     free(La);
258     free(Lb);
259 }
260 
261 //獲得第i個元素
262 Status GetElem_L(LinkList &L, int i, ElemType &e){
263     LinkList p;
264     p = L;
265     int j = 0;
266     if(i < 1){
267         exit(OVERFLOW);//下表不合法
268     }
269     while(p && j < i){
270         p = p->next;//尋找第i個元素,同時檢查p是否越界
271         j++;
272     }
273     if(!p || j > i){
274         return false;//下標越界
275     }
276     e = p->data;
277     return OK;
278 }
279 
280 //冒泡排序法排序單鏈表
281 void Sort_L(LinkList &L){
282     LinkList p,q;
283     int num;
284     for(p = L; p != NULL; p = p->next){
285         for(q = p->next;q != NULL; q = q->next){
286             if(p->data > q->data){
287                 num = p->data;
288                 p->data = q->data;
289                 q->data = num;
290             }
291         }
292     }
293 }
294 
295 //打印鏈表節點信息
296 void PrintfList_L(LinkList L){
297     if(L){
298         do{
299             L = L->next;
300             printf("%d ",L->data);
301         }while(L->next);
302     }
303     printf("\n");
304 }
305 
306 /***********************雙向鏈表實現*************************/
307 //單鏈表初始化
308 Status InitList_Du(DuLinkList &L){
309     L = (DuLinkList)malloc(sizeof(DulNode));
310     if(!L){
311         exit(OVERFLOW);  //分配存儲空間失敗
312     }
313     L->next = NULL; //初始的頭結點爲空
314     L->prior = NULL;
315     return OK;
316 }
317 
318 //在雙向鏈表中第n個位置插入元素e;
319 Status ListInsert_Dul(DuLinkList &P, int n, ElemType e){
320     DuLinkList L = P;
321     int j = 0;//記錄插入點的位置
322     while(L && j < n - 1 && n > 0){
323         L = L->next;
324         j++;
325     }
326     if(L){//合法
327         DuLinkList c;
328         c = (DuLinkList)malloc(sizeof(DulNode));
330         c->data = e;
331         c->next = L->next;
332         L->next = c;
333         if(c->next){
334             c->next->prior = c;
335         }
336         c->prior = L;
337         return OK;
338     }
339 }
340 
341 //在雙向鏈表中第n個位置刪除元素,並用e返回數據;
342 Status ListDelete_Dul(DuLinkList &P, int n, ElemType &e){
343     DuLinkList L = P;
344     int j = 0;//記錄插入點的位置
345     while(L && j < n && n > 0){
346         L = L->next;
347         j++;
348     }
349     if(L){//合法
350         e = L->data;
351         L->prior->next = L->next;
352         L->next->prior = L->prior;
353         //free(L);
354         return OK;
355     }
356 }
357 
358 //打印雙向鏈表的數據
359 void PrintList_Du(DuLinkList L){
360     if(L){
361         do{
362             L = L->next;
363             printf("%d ",L->data);
364         }while(L->next);
365     }
366     printf("\n");
367 }
368 
369 //主方法
370 void main(){
371     ElemType e,f;
372     int init,i,elem;    
373     int TestData[8] = {9,1,8,5,7,2,1,3};
374     int TestDataTwo[5] = {8,3,2,6,1};
375     
376     printf("*************線性表順序實現*************\n");
377     SqList La,Lb,Lc;
378     init = InitList(La, LIST_INIT_SIZE);
379     
380     for (i = 0; i < 8; i++) {//初始化La
381         ListInse_Sq(La, TestData[i], i);
382     }
383     printf("La:\n構造後的La:");
384     PrintList(La);
385     
386     GetElem(La,3,e);//獲得第3個元素
387     printf("獲得La的第3個元素是:%d\n",e);
388 
389     ListDelete_sq(La,3,e);//線性表的刪除操做
390     printf("刪除後的La:");
391     PrintList(La);
392 
393     ListInse_Sq(La,e,3);//還原數據
394   
395     Sort(La);//排序  
396     printf("排序後的La:");
397     PrintList(La);
398 
399     printf("Lb:\n構造後的Lb:");
400     InitList(Lb, LIST_INIT_SIZE);
401     for (i = 0; i < 5; i++) {  
402         ListInse_Sq(Lb, TestDataTwo[i], i);
403     }
404     PrintList(Lb);
405 
406     Sort(Lb);//排序Lb
407     printf("排序後的Lb:");
408     PrintList(Lb);
409 
410     printf("合併La與Lb後的Lc:");//合併La,Lb
411     Combine(La, Lb, Lc);
412     PrintList(Lc);
413 
414     printf("\n*************線性錶鏈式實現*************\n");
415     LinkList LaL,LbL,LcL,LdL;
416     //CreateList_L(LbL,5)//逆序創建單鏈表
417     InitList_L(LaL);//初始化單鏈表
418     printf("LaL:\n構造後的LaL:");
419     for (i = 1; i <= 8; i++) {//初始化La
420         ListInsert_L(LaL, i, TestData[i-1]);
421     }
422 
423     PrintfList_L(LaL);//打印單鏈表信息
424 
425     GetElem_L(LaL,3,e);//獲得第3個元素
426     printf("獲得LaL的第3個元素是:%d\n",e);
427 
428     ListInsert_L(LaL,3,10);//插入新元素
429     printf("插入後的LaL:");
430     PrintfList_L(LaL);
431     
432     ListDelete_L(LaL,3,e);//刪除添加的新元素
433     printf("刪除後的LaL:");
434     PrintfList_L(LaL);
435 
436     Sort_L(LaL);//排序  
437     printf("排序後的LaL:");
438     PrintfList_L(LaL);
439     
440     printf("LbL:\n構造後的LbL:");
441     InitList_L(LbL);//初始化單鏈表
442     
443     for (i = 1; i < 6; i++) {  
444         ListInsert_L(LbL, i, TestDataTwo[i-1]);
445     }
446     PrintfList_L(LbL);
447     
448     printf("排序後的LbL:");
449     Sort_L(LbL);//排序  
450     PrintfList_L(LbL);
451 
452     printf("合併La與Lb後的Lc:");
453     InitList_L(LcL);//初始化單鏈表
454     Combine_L(LaL, LbL, LcL);
455     PrintfList_L(LcL);
456 
457     printf("\n*************雙向鏈表的實現*************\n");
458     DuLinkList DuLa;
459     //初始化雙向鏈表
460     InitList_Du(DuLa);
461     
462     for (i = 1; i < 9; i++) {
463         ListInsert_Dul(DuLa, i, TestData[i-1]);
464     }
465     printf("DuLa:\n構造後的DuLa:");
466     PrintList_Du(DuLa);
467     printf("添加新元素元素後的DuLa:");
468     ListInsert_Dul(DuLa, 3, 10); //在第三個位置添加元素10
469     PrintList_Du(DuLa);
470 
471     printf("刪除新添加元素後的DuLa:");
472     ListDelete_Dul(DuLa,3,e);//刪除元素
473     PrintList_Du(DuLa);
474 
475 }

 

 

 運行結果:數組

須要補充一下知識點:C語言動態內存分配,C動態內存分配主要有這幾個函數:malloc、free、calloc、realloc數據結構

malloc:原型 void *malloc(unsigned size)

size表示分配內存的大小,函數會從內存池裏取一塊連續的內存,返回指向內存起始位置的指針,這塊內存進行初始化,須要手動初始化也能夠經過calloc初始化。函數

注意:malloc分配的是連續的內存。可用內存小於請求,malloc向操做系統請求獲得更多的內存,若是沒法提供更多內存,則返回一個NULL指針。學習

例如:初始化線性表(構造空的線性表 )
L.elem = (ElemType *)malloc(lenght * sizeof(ElemType));

calloc:原型 void*calloc(unsigned n,unsigned size)spa

其中n表示須要分配內存的數據項個數,size指每一個數據項的大小。malloc和calloc之間主要區別:calloc返回指向內存的指針以前把它初始化未0。 請求內存數量的方式不一樣。操作系統

realloc:原型:void *realloc(void*list,unsigned size)3d

將list所指的已分配內存區的大小改成size。realloc是修改一個原先已經分配的內存塊的大小。若是原先的內存塊沒法改變大小,realloc將分配另外一塊正確大小的內存,並把原先那塊內存的內容複製到新的快上。指針

例如:ElemType *newbase = (ElemType *)realloc(L.elem ,(L.listsize +LISTINCREMENT)*sizeof(ElemType)); 
free():  原型:void free (void* list);
  C語言中,free能夠釋放calloc, malloc, realloc動態分配的空間,注意:釋放的不是本身定義的指針,而是定義的指針指向的空間。本身定義的普通指針能不能能夠經過free釋放,這個要看狀況。若是定義的指針指向動態分配的地址空間,則可使用free釋放指針指向的這段空間;不然,就不能使用free釋放指針指向的空間。
相關文章
相關標籤/搜索