彻底理解链表中为何使用二级指针或者一级指针的引用

数据结构之链表-链表实现及常用操作(C++篇)

  C语言实现单链表,主要功能为空链表创建,链表初始化(头插法),链表元素读取,按位置插入,(有序链表)按值插入,按位置删除,按值删除,清空链表,销毁链表。

  关键思路:(1)将结点创建结构体;(2)链表中添加头结点,以便统一操作;(3)使用结点一级指针和二级指针的异同点;(4)链表的最小操作单位是结点;(5)操作的起始位置是头结点还是第一个结点,及起始索引是0还是1. 

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <time.h>
  4 
  5 //涉及到结构体自引用
  6 typedef struct Node{
  7     int data;
  8     struct Node *next;
  9 }Node;
 10 
 11 //创建空链表
 12 //必须用二级指针,涉及到头指针的创建
 13 int iniList(Node **List){
 14     *List = (Node *)malloc(sizeof(Node));
 15     if (NULL == *List){
 16         return 0;
 17     }
 18 
 19     (*List)->next = NULL; //创建头结点
 20     return 1;
 21 }
 22 
 23 //初始化链表(头插法)
 24 //必须二级指针
 25 int iniListHead(Node **List, int n){
 26     *List = (Node *)malloc(sizeof(Node));
 27     if (NULL == *List){
 28         return 0;
 29     }
 30     (*List)->next = NULL;
 31     srand(time(0));
 32 
 33     int i = 0;
 34     while (i < n){
 35         Node *tmpNode = (Node *)malloc(sizeof(Node));
 36         if (NULL == tmpNode){
 37             return 0;
 38         }
 39         tmpNode->data = rand() % 100 + 1;
 40         tmpNode->next = (*List)->next;
 41         (*List)->next = tmpNode;
 42         
 43 
 44         ++i;
 45     }
 46     return 1;
 47 }
 48 
 49 //初始化链表(尾插法)
 50 //必须二级指针
 51 //需要借助辅助变量pCurrent,将每次尾插的新元素当做当前元素
 52 int iniListTail(Node **List, int n){
 53     *List = (Node *)malloc(sizeof(Node));
 54     if (NULL == *List){
 55         return 0;
 56     }
 57     (*List)->next = NULL;
 58     srand(time(0));
 59 
 60     Node *pCurrent = *List;
 61 
 62     int i = 0;
 63     while (i < n){
 64         Node *tmpNode = (Node *)malloc(sizeof(Node));
 65         if (NULL == tmpNode){
 66             return 0;
 67         }
 68         tmpNode->data = rand() % 100 + 1;
 69         tmpNode->next = NULL;
 70         pCurrent->next = tmpNode;
 71         pCurrent = tmpNode;
 72 
 73         ++i;
 74     }
 75     return 1;
 76 }
 77 
 78 //清空链表(不删除头结点)
 79 //一级,二级指针均可
 80 //首先找到链表地址,然后移动至表尾
 81 //判断条件为指针域是否为空,即到达结尾
 82 int deleteList(Node *List){
 83 
 84     //这种方法无法删除尾结点
 85     //Node *p= List;
 86     //Node *q = NULL;
 87     //
 88     //while (p->next){
 89     //    q = p;
 90     //    free(p);
 91     //    p = q->next;
 92     //}
 93 
 94     Node *p = List->next;
 95     Node *q = NULL;
 96 
 97     while (p){
 98         q = p->next;
 99         free(p);
100         p = q;
101     }
102 
103     List->next = NULL;
104     return 1;
105 }
106 
107 //销毁链表
108 //必须使用二级指针,销毁头结点和头指针
109 //最后将链表头指针置空
110 int desrotyList(Node **List){
111 
112     Node *p = *List;
113     Node *q = NULL;
114 
115     //如果为空链表,直接删除头结点
116     //如果不是空链表,从头结点开始删除
117     while (p){
118         q = p->next;
119         free(p);
120         p = q;
121     }
122     (*List) = NULL;
123 
124     //下面是从第一个结点开始删除
125     //最后释放掉头结点
126     //Node *p = (*List)->next;
127     //Node *q = NULL;
128     //
129     //while (p){
130     //    q = p->next;
131     //    free(p);
132     //    p = q;
133     //}
134     //free(*List);
135     //(*List) = NULL;
136 
137     return 1;
138 }
139 
140 //链表获取元素
141 //一级,二级指针均可
142 //头结点无意义,从第一个结点开始遍历,i从1开始
143 //每次都指向下一结点,到pos-1即可
144 int getList(Node *List, int pos, int *element){
145     Node *p = List->next;
146     
147     int i = 1;
148     while (p && i < pos){
149         p = p->next;
150         ++i;
151     }
152     *element = p->data;
153     return 1;
154 }
155 
156 //链表按位置插入
157 //一级,二级指针均可
158 //从头结点开始,有可能插入在第一个位置,遍历从1开始
159 int insertListPos(Node *List, int pos, int value){
160     Node *p = List;
161 
162     int i = 1;
163     while (p && i < pos){
164         p = p->next;
165         ++i;
166     }
167     Node *tmpNode = (Node *)malloc(sizeof(Node));
168     tmpNode->data = value;
169     tmpNode->next = p->next;
170     p->next = tmpNode;
171     return 1;
172 }
173 
174 //有序链表,按值插入
175 //一二级指针均可
176 int insertListValue(Node *List, int value){
177     Node *pCur = List->next;
178     Node *pPer = List;
179     while (pCur && pCur->data < value){
180         pPer = pCur;
181         pCur = pCur->next;
182     }
183 
184     Node *tmpNode = (Node *)malloc(sizeof(Node));
185     if (NULL == tmpNode){
186         return 0;
187     }
188     tmpNode->data = value;
189     tmpNode->next = pPer->next;
190     pPer->next = tmpNode;
191     return 1;
192 }
193 
194 //链表按位置删除
195 //一二级指针均可
196 //记得释放结点内存
197 //如果删除第一个结点,需要操纵头结点
198 int deleteListPos(Node *List, int pos){
199     Node *p = List;
200 
201     int i = 1;
202     while (p && i < pos){
203         p = p->next;
204         ++i;
205     }
206     if (NULL == p->next)
207         return 0;
208 
209     Node *tmpNode = p->next;
210     p->next = p->next->next;
211     
212     free(tmpNode);
213     return 1;
214 }
215 
216 //链表按值删除元素
217 //一二级指针均可
218 //从第一个结点开始
219 int deleteListValue(Node *List, int value){
220     Node *pCur = List->next;
221     Node *pPer = List;
222 
223     while (pCur && pCur->data != value){
224         pPer = pCur;
225         pCur = pCur->next;
226     }
227     if (pCur == NULL){ //空链表不删除任何结点
228         return 0;
229     }
230     else{
231         pPer->next = pCur->next;
232         free(pCur);
233     }
234     return 1;
235 }
236 
237 int main(){
238 
239     Node *testList = NULL;
240     iniList(&testList);
241     //iniListHead(&testList, 3);
242     //iniListTail(&testList, 3);
243     
244 
245     insertListPos(testList, 1, 2);
246     insertListPos(testList, 2, 4);
247     insertListPos(testList, 3, 5);
248     insertListPos(testList, 4, 10);
249     //insertListPos(testList, 1, 1);
250     insertListValue(testList, 1);
251 
252     //deleteListPos(testList, 1);
253     //deleteListValue(testList, 4);
254 
255     //deleteList(testList);
256 
257     //printf("%d\n", testList);
258     //desrotyList(&testList);
259     //printf("%d\n", testList);
260 
261     Node * tmpNode = testList->next;
262     while (tmpNode){
263         printf("%d\n", tmpNode->data);
264         tmpNode = tmpNode->next;
265     }
266 
267     printf("----------------------\n");
268 
269     int a = 0;
270     getList(testList, 2, &a);
271     printf("%d\n", a);
272 
273     system("pause");
274 
275     return 0;
276 }
C语言完整代码

相关文章: