1 #define ElemType int 2 #define OK 1 3 #define ERROR -1 4 #define Status int 5 6 typedef struct Lnode{ 7 ElemType data; 8 struct LNode *next; 9 }LNode, *LinkList; 10 //LinkList 相當於 LNode *
遇到的問題:
1.鏈表傳入函數中要真正改變內容要對頭節點的指針內容進行修改, 這里要區分開頭節點和頭節點的指針,
頭節點的指針是LinkList 型的可以存儲一個節點的地址,而頭節點是一個實實在在的節點,它被頭節點的指針索引。
2.上面定義的 * LinkList 其實和LNode * 是等價的 , 所以在開辟節點時候可以直接寫: p = (LinkList)malloc(sizeof(LNode));
兩種創建鏈表的方式:
1 Status CreatList_L1(LinkList *L, int n) 2 { 3 //尾插法創建鏈表 4 //要將創建的鏈表返回,所以要傳入指針LinkList *L 5 LinkList p, q; 6 q = *L = (LinkList)malloc(sizeof(LNode)); 7 (*L)->next = NULL; 8 for(int i=0; i < n; i++) 9 { 10 p = (LinkList)malloc(sizeof(LNode)); 11 scanf("%d", &p->data); 12 q->next = p; 13 q = p; 14 } 15 p->next = NULL; 16 return OK; 17 }//CreatList_L1
1 Status CreatList_L2(LinkList *L, int n) 2 { 3 //頭插法創建鏈表 4 (*L) = (LinkList)malloc(sizeof(LNode)); 5 (*L) ->next = NULL; //頭插法一定加上這句 6 LinkList s; 7 for(int i=0; i < n; i++) 8 { 9 s = (LinkList)malloc(sizeof(LNode));//生成新節點 10 scanf("%d",&s->data); 11 s->next = (*L)->next; //將新開辟的節點查到頭節點后面 12 (*L)->next = s; 13 } 14 return OK; 15 }//CreatList_L2
查詢鏈表第i個位置的元素,並返回其值:
1 Status GetElem_L(LinkList L, int i, ElemType *e) 2 { 3 //L為帶頭節點的單鏈表的頭指針 4 //但第i個元素存在時,其值賦給e並返回OK,否則返回ERROR 5 LinkList p = L; //初始化,p指向第1個節點 6 int j = 0; //計數器 7 while(p && j < i) //順時針向后查找,直到p指向第i個元素或p為空 8 { 9 p = p->next; 10 j++; 11 } 12 if(!p || j > i) //第i個元素不存在 13 return ERROR; 14 *e = p->data; //取第i個元素 15 return OK; 16 }//GetElem_L
插入:
1 Status ListInsert_L(LinkList L, int i, ElemType e) 2 { 3 //在帶頭節點的單鏈線性表L第i個位置之前插入元素e 4 LinkList p = L, s; 5 int j = 0; 6 while(p && j < i-1) //尋找第i個節點,並令p指向其前驅 7 { 8 p = p->next; 9 j++; 10 } 11 if(!p || j > i - 1) //i小於1或着大於表長+1 12 return ERROR; 13 s = (LinkList)malloc(sizeof(LNode)); //生成新節點 14 s->data = e; //給新節點賦值 15 s ->next = p->next; //新節點指向第i個節點 16 p->next = s; //第i-1個節點指向新節點 17 return OK; 18 }//ListInsert_L
刪除:
1 Status ListDelete_L(LinkList L, int i, ElemType *e) 2 { 3 //在帶頭節點的單鏈線性表L中,刪除第i個元素,並由e返回其值 4 LinkList p = L, q; 5 int j = 0; 6 while(p && j < i-1) //尋找第i個元素,並令p指向其前驅 7 { 8 p = p->next; 9 j++; 10 } 11 if(!p || j > i-1) //刪除位置不合理 12 return ERROR; 13 q = p->next; //q指向刪除節點 14 *e = q->data; //e保存其值 15 p -> next = q->next; //移動指針跳過該節點 16 free(q); //釋放空間 17 return OK; 18 }//ListDelete_L
合並:
1 void MergeList_L(LinkList La, LinkList Lb, LinkList *Lc) 2 { 3 //已知單鏈線性表La和Lb的元素按值非遞減排列 4 //歸並La和Lb得到新的單鏈線性表Lc,Lc的元素也按值非遞減排列 5 LinkList pa = La->next; 6 LinkList pb = Lb->next; 7 (*Lc) = La; //用La的頭節點作為Lc的頭節點 8 LinkList pc = *Lc; 9 while(pa && pb) //與順序表類似 10 { 11 if(pa->data <= pb->data) 12 { 13 pc->next = pa; 14 pc = pa; 15 pa = pa->next; 16 } 17 else 18 { 19 pc->next = pb; 20 pc = pb; 21 pb = pb->next; 22 } 23 } 24 pc->next = pa ? pa : pb; //插入剩余段 25 free(Lb); //釋放Lb的頭節點 26 }//MergeList_L
下面是完整代碼,可以試一下:

1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define ElemType int 5 #define OK 1 6 #define ERROR -1 7 #define Status int 8 9 typedef struct Lnode{ 10 ElemType data; 11 struct LNode *next; 12 }LNode, *LinkList; 13 //LinkList 相當於 LNode * 14 15 Status CreatList_L1(LinkList *L, int n) 16 { 17 //尾插法創建鏈表 18 //要將創建的鏈表返回,所以要傳入指針LinkList *L 19 LinkList p, q; 20 q = *L = (LinkList)malloc(sizeof(LNode)); 21 (*L)->next = NULL; 22 for(int i=0; i < n; i++) 23 { 24 p = (LinkList)malloc(sizeof(LNode)); 25 scanf("%d", &p->data); 26 q->next = p; 27 q = p; 28 } 29 p->next = NULL; 30 return OK; 31 }//CreatList_L1 32 33 Status CreatList_L2(LinkList *L, int n) 34 { 35 //頭插法創建鏈表 36 (*L) = (LinkList)malloc(sizeof(LNode)); 37 (*L) ->next = NULL; //頭插法一定加上這句 38 LinkList s; 39 for(int i=0; i < n; i++) 40 { 41 s = (LinkList)malloc(sizeof(LNode));//生成新節點 42 scanf("%d",&s->data); 43 s->next = (*L)->next; //將新開辟的節點查到頭節點后面 44 (*L)->next = s; 45 } 46 return OK; 47 }//CreatList_L2 48 49 Status GetElem_L(LinkList L, int i, ElemType *e) 50 { 51 //L為帶頭節點的單鏈表的頭指針 52 //但第i個元素存在時,其值賦給e並返回OK,否則返回ERROR 53 LinkList p = L; //初始化,p指向第1個節點 54 int j = 0; //計數器 55 while(p && j < i) //順時針向后查找,直到p指向第i個元素或p為空 56 { 57 p = p->next; 58 j++; 59 } 60 if(!p || j > i) //第i個元素不存在 61 return ERROR; 62 *e = p->data; //取第i個元素 63 return OK; 64 }//GetElem_L 65 66 Status ListInsert_L(LinkList L, int i, ElemType e) 67 { 68 //在帶頭節點的單鏈線性表L第i個位置之前插入元素e 69 LinkList p = L, s; 70 int j = 0; 71 while(p && j < i-1) //尋找第i個節點,並令p指向其前驅 72 { 73 p = p->next; 74 j++; 75 } 76 if(!p || j > i - 1) //i小於1或着大於表長+1 77 return ERROR; 78 s = (LinkList)malloc(sizeof(LNode)); //生成新節點 79 s->data = e; //給新節點賦值 80 s ->next = p->next; //新節點指向第i個節點 81 p->next = s; //第i-1個節點指向新節點 82 return OK; 83 }//ListInsert_L 84 85 Status ListDelete_L(LinkList L, int i, ElemType *e) 86 { 87 //在帶頭節點的單鏈線性表L中,刪除第i個元素,並由e返回其值 88 LinkList p = L, q; 89 int j = 0; 90 while(p && j < i-1) //尋找第i個元素,並令p指向其前驅 91 { 92 p = p->next; 93 j++; 94 } 95 if(!p || j > i-1) //刪除位置不合理 96 return ERROR; 97 q = p->next; //q指向刪除節點 98 *e = q->data; //e保存其值 99 p -> next = q->next; //移動指針跳過該節點 100 free(q); //釋放空間 101 return OK; 102 }//ListDelete_L 103 104 void MergeList_L(LinkList La, LinkList Lb, LinkList *Lc) 105 { 106 //已知單鏈線性表La和Lb的元素按值非遞減排列 107 //歸並La和Lb得到新的單鏈線性表Lc,Lc的元素也按值非遞減排列 108 LinkList pa = La->next; 109 LinkList pb = Lb->next; 110 (*Lc) = La; //用La的頭節點作為Lc的頭節點 111 LinkList pc = *Lc; 112 while(pa && pb) //與順序表類似 113 { 114 if(pa->data <= pb->data) 115 { 116 pc->next = pa; 117 pc = pa; 118 pa = pa->next; 119 } 120 else 121 { 122 pc->next = pb; 123 pc = pb; 124 pb = pb->next; 125 } 126 } 127 pc->next = pa ? pa : pb; //插入剩余段 128 free(Lb); //釋放Lb的頭節點 129 }//MergeList_L 130 131 int main() 132 { 133 int n; 134 LinkList L, p, s; 135 scanf("%d",&n); 136 CreatList_L1(&L, n); 137 printf("\n~~~\n"); 138 p = L->next; 139 while( p != NULL){ 140 printf("%d ",p->data); 141 p = p->next; 142 } 143 printf("\n"); 144 145 int i, e; 146 printf("查詢位置: "); 147 scanf("%d",&i); 148 GetElem_L(L, i, &e); 149 printf("e == %d\n",e); 150 151 printf("插入位置、元素:"); 152 scanf("%d%d",&i,&e); 153 ListInsert_L(L, i, e); 154 p = L->next; 155 while(p){ 156 printf("%d ",p->data); 157 p = p->next; 158 } 159 printf("\n"); 160 161 printf("刪除位置:"); 162 scanf("%d",&i); 163 ListDelete_L(L, i, &e); 164 printf("e == %d\n",e); 165 166 int a[ ]= {3, 5, 8, 11}; 167 int b[ ]= {2, 6, 8, 9, 11, 15, 20}; 168 LinkList La, Lb; 169 La = (LinkList)malloc(sizeof(LNode)); 170 Lb = (LinkList)malloc(sizeof(LNode)); 171 La->next = Lb->next = NULL; 172 p = La; 173 for(int i = 0; i < sizeof(a)/sizeof(a[0]); i++) 174 { 175 s = (LinkList)malloc(sizeof(LNode)); 176 s->data = a[i]; 177 p->next = s; 178 p = s; 179 } 180 p->next = NULL; 181 182 p = Lb; 183 for(int i = 0; i<sizeof(b)/sizeof(b[0]); i++) 184 { 185 s = (LinkList)malloc(sizeof(LNode)); 186 s->data = b[i]; 187 p->next = s; 188 p = s; 189 } 190 p->next = NULL; 191 192 printf("La = "); 193 p = La->next; 194 while(p) 195 { 196 printf("%d ",p->data); 197 p = p->next; 198 } 199 printf("\n"); 200 p = La->next; 201 202 printf("Lb = "); 203 p = Lb->next; 204 while(p) 205 { 206 printf("%d ",p->data); 207 p = p->next; 208 } 209 printf("\n"); 210 211 LinkList Lc; 212 MergeList_L(La, Lb, &Lc); 213 214 printf("MergeList = "); 215 p = Lc->next; 216 while(p) 217 { 218 printf("%d ", p->data); 219 p = p->next; 220 } 221 printf("\n"); 222 223 224 return 0; 225 }