[数据结构与算法] 单链表的简单demo

Vc6之下编译通过。。

 1 /*******************************************************
 2 * @: Project:    单链表数据结构演示
 3 * @: File:        link_list.h
 4 * @: Function: 提供单链表操作的数据结构定义及方法声明
 5 * @: History:    2013-10-01 22:37:05
 6 * @: Author:    Alimy
 7 *******************************************************/
 8 /*******************************************************
 9 * @:头文件包含
10 *******************************************************/
11 
12 #ifndef __LINK_LIST_H__
13 #define __LINK_LIST_H__
14 /*******************************************
15 * @: 数据结构定义&一些宏
16 ********************************************/
17 #define ElemType   signed short    int            // 此例子中的数据为有符号短整形,在VC6 中占据16bits
18 #define StatusType    int        //操作状态为int类型
19 #define OK    (StatusType)1
20 #define ERROR (StatusType)0
21 
22 typedef struct LNode{
23     ElemType m_data;              // 数据域
24     struct LNode *p_next;     // 指针域
25 } LNode, *pLinkList;
26 
27 //typedef struct LHead{ //头结点,其实和 LNode的内存结构相似,
28 //    int ElemNumber;  //数据域,可以存储当前线性表的长度,也可以什么也不存储
29 //    struct LNode *p_FirstNode; //指针域指向线性表的第一个元素
30 //}LHead, *pLHead;
31 
32 #define DATA_FIELD    0//定义是否让头结点的数据域存储表长信息 1为存储(头结点模式),0为不存储(非头结点模式)
33 
34 /*******************************************
35 * @: 外部调用函数声明
36 ********************************************/
37 extern StatusType CreateList_L(pLinkList *pL,int num);//构造num个结点的单链表
38 //extern StatusType _CreateList_L(pLinkList *pL,int num);
39 extern StatusType GetElem_L(pLinkList *pL,int idx_location, ElemType* pe); //获取单链表的元素
40 extern StatusType InsertElem_L(pLinkList *pL,int idx_location,ElemType e);//在单链表中插入元素
41 extern StatusType DeleteElem_L(pLinkList *pL,int idx_location,ElemType* pe);//在单链表中删除元素
42 extern void ClearList_L(pLinkList *pL);    //整表删除
43 extern int LocateElem_L(pLinkList *pL,ElemType e); //定位元素
44 extern int GetLength_L(pLinkList *pL);
45 
46 extern void MergeList_L1(pLinkList *pLa,pLinkList *pLb,pLinkList *pLc);//将两个有序链表并为一个有序链表
47 extern void MergeList_L2(pLinkList *pLa,pLinkList *pLb,pLinkList *pLc);//将两个有序链表并为一个有序链表
48 
49 
50 extern void DisplayList_L(pLinkList *pL); //显示当前所有单链表的长度
51 #endif // end of __LINK_LIST_H__
link_list.h
  1 /*******************************************************
  2 * @: Project:    单链表数据结构演示
  3 * @: File:        link_list.c
  4 * @: Function: 提供单链表操作的基本函数和方法
  5 * @: History:    2013-10-01 22:37:37
  6 * @: Author:    Alimy
  7 *******************************************************/
  8 
  9 /*******************************************************
 10 * @: 头文件包含 
 11 *******************************************************/
 12 #include "link_list.h"
 13 #include <stdio.h> 
 14 #include <conio.h>    // int getch(void);
 15 #include <stdlib.h>  // int rand(void);  malloc(); free();
 16 #include <time.h>    // time_t time(time_t *);
 17 
 18 /*******************************************************
 19 * @: (外部&内部)变量声明及定义
 20 *******************************************************/
 21 
 22 /*******************************************************
 23 * @: (外部&内部)函数声明及定义
 24 *******************************************************/
 25 StatusType CreateList_L(pLinkList *pL,int num);//构造num个结点的单链表
 26 StatusType GetElem_L(pLinkList *pL,int idx_location, ElemType* pe); //获取单链表的元素
 27 StatusType InsertElem_L(pLinkList *pL,int idx_location,ElemType e);//在单链表中插入元素
 28 StatusType DeleteElem_L(pLinkList *pL,int idx_location,ElemType* pe);//在单链表中删除元素
 29 int LocateElem_L(pLinkList *pL,ElemType e); //定位元素
 30 int GetLength_L(pLinkList *pL);//获得表长
 31 void ClearList_L(pLinkList *pL);    //整表删除
 32 
 33 void DisplayList_L(pLinkList *pL); //显示当前所有单链表的长度
 34 
 35 
 36 
 37 
 38 
 39 
 40 /*******************************************************
 41 * @: 内部函数具体实现
 42 *******************************************************/
 43 
 44 //ElemType s_data[] = {1,2,3,4,5,6,7,8,9,10,11};
 45 
 46 /*
 47 *@:在堆中构造一个单链表,并逆序插入num个结点(头插法)
 48 *@:返回值 
 49 *@:    构造成功返回OK
 50 *@: 构造失败返回ERROR
 51 **/
 52 StatusType CreateList_L(pLinkList *pL,int num){//构造num个结点的单链表
 53     LNode*  p_Work = NULL; //工作指针
 54     int idx = 0;
 55     if(*pL!=NULL){
 56         printf("当前单链表已被初始化,不需要执行Create操作 
");
 57         return ERROR;
 58     }
 59 
 60     *pL = (pLinkList)malloc(sizeof(LNode));
 61     if(*pL == NULL){
 62         printf("在堆中申请头结点失败 
");
 63         return ERROR;        
 64     }
 65     (*pL)->m_data = 0;  // 数据域可以存储当前单链表的长度
 66     (*pL)->p_next = NULL;
 67     
 68     srand(time(0));
 69     for(idx=0;idx<num;idx++){
 70         p_Work = (pLinkList)malloc(sizeof(LNode)); //在堆中申请新的结点
 71         if(p_Work==NULL){
 72             printf("在堆中申请结点出现异常,构造单链表失败  
");
 73             return ERROR;
 74         }
 75 
 76         //p_Work->m_data = 10*s_data[idx%10];//(rand()%(10)); //均为10以内的整数
 77         p_Work->m_data = (rand()%(100))+1; //晕死,每次生产的随机数怎么都一样
 78         p_Work->p_next = (*pL)->p_next;
 79         (*pL)->p_next = p_Work;          //逆序插入,第一个产生为表尾
 80     }
 81 
 82     (*pL)->m_data = num;
 83 
 84 //    printf("构造单链表成功,单链表的当前长度为 【%d】 
",(*pL)->m_data);
 85 //    printf("单链表的元素值依次是 
");
 86 //    p_Work = (*pL);  //指向头结点
 87 //    idx = 0;
 88 //    while(p_Work->p_next){// p_ Work->p_next != NULL 
 89 //        idx++;        
 90 //        p_Work = p_Work->p_next;
 91 //        printf("单链表的第【%d】个元素的值为【%d】
",idx,p_Work->m_data);
 92 
 93 //    }
 94     printf("构造含【%d】个元素的单链表成功,按任意键去到主菜单
",(*pL)->m_data);
 95     getch();
 96     return OK;
 97 }
 98 //StatusType _CreateList_L(pLinkList *pL,int num){//构造num个结点的单链表(尾插法)
 99 //    LNode*  p_Work = NULL;
100 //    LNode*  p_NewNode = NULL; //指向新申请结点
101 //    LNode*  p_LastNode = NULL; //指向当前单链表的最后一个结点
102 //    int idx = 0;
103 //    if(*pL!=NULL){
104 //        printf("当前单链表已被初始化,不需要执行Create操作 
");
105 //        return ERROR;
106 //    }
107 //
108 //    *pL = (pLinkList)malloc(sizeof(LNode));//(建立头结点)
109 //    if(*pL == NULL){
110 //        if(*pL == NULL){
111 //            printf("在堆中申请头结点失败 
");
112 //            return ERROR;        
113 //        }
114 //
115 //    }
116 //    (*pL)->m_data = 0;  // 数据域可以存储当前单链表的长度  
117 //    (*pL)->p_next = NULL;
118 //    p_LastNode = (*pL);
119 //    srand(time(0));
120 //    for(idx=0;idx<num;idx++){
121 //        p_NewNode = (LNode*)malloc(sizeof(LNode));
122 //        if(p_NewNode == NULL){
123 //            printf("在堆中申请新结点失败 
");
124 //            return ERROR;
125 //        }
126 //        p_NewNode->m_data = (rand()%(10)); 
127 //        p_NewNode->p_next = NULL;
128 //        p_LastNode->p_next = p_NewNode;
129 //        p_LastNode = p_NewNode;
130 //    }
131 //
132 //    (*pL)->m_data = num;
133 //
134 //    printf("构造单链表成功,单链表的当前长度为 【%d】 
",(*pL)->m_data);
135 //    printf("单链表的元素值依次是 
");
136 //    
137 //    p_Work = (*pL);  //指向头结点
138 //    idx = 0;
139 //    while(p_Work->p_next){// p_ Work->p_next != NULL 
140 //        idx++;        
141 //        p_Work = p_Work->p_next;
142 //        printf("单链表的第【%d】个元素的值为【%d】
",idx,p_Work->m_data);
143 //    }
144 //    printf("构造含【%d】个元素的单链表成功,按任意键去到主菜单",(*pL)->m_data);
145 //    getch();
146 //    return OK;
147 //}
148 
149 
150 
151 /*
152 *@:定位pL指向的单链表的第idx_location 个元素,并将该元素的值赋值给pe指向的内存
153 *@:返回值 
154 *@:    定位数据成功返回OK
155 *@: 定位数据失败返回ERROR
156 **/
157 StatusType GetElem_L(pLinkList *pL,int idx_location, ElemType* pe){ //获取单链表的元素
158     int idx = 0;
159     LNode * p_Work = NULL; // 工作指针
160     
161     #if DATA_FIELD == 0
162         p_Work = (*pL);  //工作指针指向头指针
163         idx = 0;
164         while(p_Work && idx<idx_location){  // 移动工作指针&计数判断是否有
165             p_Work = p_Work->p_next;
166             idx++;
167             // p_Work 指向第idx个结点
168         }
169     
170         if((!p_Work)||(idx>idx_location)){
171         //    printf("索引数据有(非头结点模式)
");
172             return ERROR;
173         }
174     
175         *pe = p_Work->m_data;
176         return OK;
177     #else
178         //若头结点的数据域存储了单链表的表长信息
179         if((idx_location>(*pL)->m_data)||(idx_location<1)){ //索引有误
180         //    printf("索引数据有误(头结点模式) 
");
181             return ERROR;
182         }
183         p_Work = (*pL);
184         idx = 0;        //工作指针指向头结点,计数清零
185         for(;idx<idx_location;){
186             p_Work = p_Work->p_next;
187             idx++;
188         }
189         //此时p_Work指向第idx_location个结点
190         *pe = p_Work->m_data;
191         return OK;
192     #endif
193     
194 }
195 
196 
197 
198 /*
199 *@:在pL指向的单链表的第idx_location 个位置插入值为e的元素
200 *@:返回值 
201 *@:    插入元素成功返回OK
202 *@: 插入元素失败返回ERROR
203 *@: 时间复杂度:O(n) 但是插入一个和插入N个区别不多,单链表适合(比较顺序表)插入操作较频繁的操作
204 
205 **/
206 StatusType InsertElem_L(pLinkList *pL,int idx_location,ElemType e){//在单链表中插入元素
207 
208     int idx = 0;
209     LNode* p_Work = NULL;
210     LNode* pNewNode = NULL;
211 
212     #if DATA_FIELD == 0
213         // to do 2013-10-06 00:10:46
214         p_Work = (*pL);        //工作指针指向头结点
215         idx = 0;
216 
217         while((p_Work)&&(idx<idx_location-1)){
218             idx++;
219             p_Work = p_Work->p_next;
220         }  
221         //正常情况下,p_Work应该指向第【idx_location - 1】个元素
222         if((!p_Work)||(idx>idx_location-1)){
223             printf("要插入元素的索引有误,请检查后重新输入  
");
224             return ERROR;
225         }
226         else{
227             pNewNode = (LNode *)malloc(sizeof(LNode));            
228             if(!pNewNode){
229                 printf("在插入元素时,申请堆空间失败,插入操作元素失败 
");
230                 return ERROR;
231             }
232             else{
233                 pNewNode->m_data = e;
234                 pNewNode->p_next = p_Work->p_next;
235                 p_Work->p_next = pNewNode;
236                 return OK;
237             }
238 
239 
240         }        
241     #else
242     //头结点存储了单链表的长度
243         if((idx_location<1)||(idx_location>(*pL)->m_data+1)){  // 元素索引逻辑有误
244             printf("要插入元素的索引有误,请检查后重新输入  
");
245             return ERROR;
246         }
247         else{
248             p_Work = (*pL);
249             idx = 0;        //工作指针指向头结点,计数清零
250             for(;idx<idx_location-1;){
251                 p_Work = p_Work->p_next;
252                 idx++;
253             }
254             // p_Work指向第【idx_location-1】个结点
255             pNewNode = (LNode *)malloc(sizeof(LNode));
256             if(!pNewNode){
257                 printf("在插入元素时,申请堆空间失败,插入操作元素失败 
");
258                 return ERROR;
259             }
260             else{
261                 pNewNode->m_data = e;
262                 pNewNode->p_next = p_Work->p_next;
263                 p_Work->p_next = pNewNode;        // s->next = p->next;  p->next = s;  
264                 (*pL)->m_data++;  //计数器自加
265                 printf("插入元素成功
");
266                 return OK;
267             }
268         }
269     #endif 
270 }
271 
272 
273 /*
274 *@:在pL指向的单链表中寻找第一个值为e的元素,将其索引返回
275 *@: 返回值
276 *         找到值为e的元素--->返回非0 索引值
277 *        没有找到---->    返回0
278 */
279 int LocateElem_L(pLinkList *pL,ElemType e){ //定位元素
280         int idx = 0;
281         LNode * p_Work = NULL;
282         if(*pL==NULL){
283             printf("当前单链表未被初始化,无法执行定位操作 
");
284             return 0;
285         }
286         
287         p_Work = (*pL);
288         idx = 0;        //计数清零,工作指针指向头结点
289 //_Loops:
290 //        if(p_Work->p_next!=NULL)
291 //        {
292 //            p_Work = p_Work->next;
293 //            idx++;
294 //            if(p_Work->m_data == e)
295 //                return idx;
296 //            goto _Loops;
297 //        }
298 
299         while(p_Work->p_next!=NULL){
300             p_Work = p_Work->p_next;
301             idx++;
302             if(p_Work->m_data == e){
303                 printf("找到单链表的第【%d】个元素的值为【%d】",idx,p_Work->m_data);
304                 return idx;
305             }
306         }
307         printf("没有定位到元素");
308         return 0;  // 上述没有定位到
309 
310         
311 }
312 
313 /*
314 *@:删除pL指向的单链表的第idx_location 个位置的元素,并将被删除结点的数据域赋值给pe指向的内存
315 *@:返回值 
316 *@:    删除元素成功返回OK
317 *@: 删除元素失败返回ERROR
318 *@: 时间复杂度:O(n) 但是删除一个和删除N个区别不多,单链表适合(比较顺序表)删除操作较频繁的操作
319 **/
320 StatusType DeleteElem_L(pLinkList *pL,int idx_location,ElemType* pe){//在单链表中删除元素
321     int idx = 0;
322     LNode * p_Work = NULL;
323     LNode * p_Temp = NULL;
324 
325     #if DATA_FIELD == 0
326         idx = 0;
327         p_Work = (*pL);  //工作指针指向头结点
328         while((p_Work)&&(idx<idx_location-1)){
329             idx++;
330             p_Work = p_Work->p_next;
331         }
332     //正常情况下,p_Work应该指向第【idx_location - 1】个元素
333         if((!p_Work)||(idx>idx_location-1)){
334             printf("要删除位置的索引有误,请重新输入 
");
335             return ERROR;
336         }
337         else{
338             p_Temp = p_Work->p_next;  //指向要删除的结点
339             p_Work->p_next = p_Temp->p_next;//p_Work->p_next = p_Work->p_next->p_next;
340             *pe = p_Temp->m_data;
341             free(p_Temp);
342             return OK;
343         }
344     #else
345         if((idx_location<1)||(idx_location>(*pL)->m_data)){ // 
346             printf("要删除元素位置索引有误,请检查输入 
");
347             return ERROR;
348         }
349         else{
350             p_Work = (*pL);
351             idx = 0;            //工作指针指向头结点
352             for(;idx<idx_location-1;){
353                 p_Work = p_Work->p_next;
354                 idx++;
355             }
356             //p_Work指向第【idx_location - 1 】个结点
357             p_Temp =  p_Work->p_next;
358             p_Work->p_next = p_Temp->p_next;//p_Work->p_next = p_Work->p_next->p_next;
359             *pe = p_Temp->m_data;
360             free(p_Temp);
361             (*pL)->m_data--;
362             return OK;
363         }
364         
365     #endif
366 }
367 
368 /*
369 * @:获取pL指向的单链表中的元素个数
370 * @:返回值
371 *        得到长度--->返回非0长度值
372 *        得不到长度---->返回0
373 */
374 int GetLength_L(pLinkList *pL){//获得表长
375 
376     int idx = 0;
377     LNode * p_Work = NULL;
378     if(*pL==NULL){
379         printf("当前单链表未被初始化,无法获取表长
");
380         return 0;
381     }
382     #if DATA_FIELD == 0
383         p_Work = (*pL);
384         idx = 0;        //计数清零,工作指针指向头结点
385         while(p_Work->p_next!=NULL){
386             idx++;
387             p_Work = p_Work->p_next;
388         }
389         printf("当前单链表共有【%d】个元素
",idx);
390         return idx;
391 
392     #else
393         idx = (*pL)->m_data;
394     printf("当前单链表共有【%d】个元素
",idx);
395         
396         return idx;
397 
398 
399     #endif
400 
401 }
402 /*
403 *@:删除pL指向的单链表的所有结点
404 */
405 
406 void ClearList_L(pLinkList *pL){    //整表删除
407     LNode* p_Work1 = NULL;
408     LNode* p_Work2 = NULL; //工作指针
409     
410     if(*pL == NULL){
411         printf("当前单链表未创建,无法执行整表删除操作 
");
412         return ;
413     }
414     else if((*pL)->p_next == NULL){
415         printf("当前单链表为空表,不需要执行整表删除操作 
");
416         return;
417     }
418     else{
419         p_Work1 = (*pL)->p_next; // 指向第一个结点(如果有的话)
420         while(p_Work1!=NULL){
421             p_Work2 = p_Work1;
422             p_Work1 = p_Work2->p_next;//指向下一个
423             free(p_Work2);
424         }
425 
426     //    (*pL)->p_next = NULL;        // 头结点指向NULL
427         (*pL)->m_data = 0;
428         return ;
429     }
430 }
431 
432 /*
433 *@: 输出显示pL指向的单链表所有的元素
434 */
435 void DisplayList_L(pLinkList *pL){ //显示当前所有单链表的长度
436 
437     int idx = 0;
438     LNode* p_Work = NULL;
439 
440     if(*pL==NULL){
441         printf("单链表还未构建,输不出东东 
");
442         return ;
443     }
444 
445     #if DATA_FIELD == 0
446         idx = 0;
447         p_Work = (*pL); // 工作指针指向头结点,计数清零
448         if(p_Work->p_next==NULL){
449             printf("当前单链表为空表,没什么东东好显示的 
");
450             return ;
451         }
452         else{
453             while(p_Work->p_next){ //(p_Work->p_next!=NULL)
454                 idx++;
455                 p_Work = p_Work->p_next;
456                 printf("单链表第【%d】个元素的值为【%d】
",idx,p_Work->m_data);
457             }
458             return ;
459         }
460     #else
461         if((*pL)->m_data == 0){
462             printf("当前单链表的表长为0,没有数据元素,没有什么好打印的 
");
463             return ;
464         }
465         idx = 0;
466         p_Work = (*pL);  // 工作指针指向头结点,计数清零
467         printf("单链表数据如下:
");
468         for(;idx<(*pL)->m_data;){  //  idx < currentLength   (currentLength == (*pL)->m_data  or  currentLength == GetLength_L )
469             idx++;
470             p_Work = p_Work->p_next;
471             printf("单链表第【%d】个元素的值为【%d】
",idx,p_Work->m_data);
472         }
473         return ;
474     #endif
475 
476 }
477 
478 
479 
480 
481 //演示程序中没有用到的程序
482 
483 void MergeList_L1(pLinkList *pLa,pLinkList *pLb,pLinkList *pLc);//归并两个单链表
484 /*
485 *@:归并,已知pLa和pLb指向的单链表的元素都按非递减排列
486 *    将La 和Lb中的元素归并到pLc指向的单链表中
487 */
488 void MergeList_L1(pLinkList *pLa,pLinkList *pLb,pLinkList *pLc){ // 按顺序表的方法新建结点归并到pLc,形成一个新的表,对原来的那两个单链表没有损伤
489     LNode * p_WorkLa = NULL;
490     LNode * p_WorkLb = NULL;
491     int Lc_len = 0;
492     *pLc = (LNode *)malloc(sizeof(LNode)); //*pLc进来是是未被初始化的,即(*pLc) == NULL 
493     (*pLc)->m_data = 0;
494     (*pLc)->p_next = NULL;  // 将pLc指向空表
495     
496 
497     p_WorkLa = (*pLa)->p_next;
498     p_WorkLb = (*pLb)->p_next;    // 初始化时都指向第一个结点(如果有第一个的话)
499 
500     while((p_WorkLa!=NULL)&&(p_WorkLb!=NULL)){
501         Lc_len++; //一定有可以插入的元素
502         if(p_WorkLa->m_data>=p_WorkLb->m_data){
503             InsertElem_L(pLc,Lc_len,p_WorkLb->m_data);
504             p_WorkLb = p_WorkLb->p_next;    
505         }
506         else{
507             InsertElem_L(pLc,Lc_len,p_WorkLa->m_data);
508             p_WorkLa = p_WorkLa->p_next;
509         }
510     }
511 
512     while(p_WorkLa!=NULL){
513         Lc_len++;
514         InsertElem_L(pLc,Lc_len,p_WorkLa->m_data);
515         p_WorkLa = p_WorkLa->p_next;
516     }
517 
518     while(p_WorkLb!=NULL){
519         Lc_len++;
520         InsertElem_L(pLc,Lc_len,p_WorkLb->m_data);
521         p_WorkLb = p_WorkLb->p_next;
522     }
523 }
524 
525 
526 void MergeList_L2(pLinkList *pLa,pLinkList *pLb,pLinkList *pLc){//不新建结点,就用链表把la和lb中的元素用指针连接起来也成为lc的结点
527     LNode* p_la = NULL;
528     LNode* p_lb = NULL;
529     LNode* p_lc = NULL;
530 
531     p_la = (*pLa)->p_next;
532     p_lb = (*pLc)->p_next;    // 都指向第一个结点
533 
534     pLc = p_lc = p_la; //用La的头结点作为Lc的头结点
535 
536     while((p_la!=NULL)&&(p_lb!=NULL)){
537         if(p_la->m_data <= p_lb->m_data){
538             p_lc->p_next = p_la;
539             p_lc = p_la;    // 工作指针移动
540             p_la = p_la->p_next;
541         }
542         else{
543             pLc->p_next = p_lb;
544             p_lc = p_lb;
545             p_lb = p_lb->p_next;
546         }
547     }
548 
549     if(p_la != NULL){
550         p_lc->p_next = p_la;
551     }
552 
553     if(p_lb != NULL){
554         p_lc->p_next = p_lb;
555     }
556 
557     free(*(pLb));//释放Lb结点
558     (*pLb)->p_next = NULL;//Lb被直接置为空表了!
559         
560 }
link_list.c
  1 /*******************************************************
  2 * @: Project:    单链表数据结构演示
  3 * @: File:        main.c
  4 * @: Function: 单链表demo主程序
  5 * @: History:    2013-10-01 22:36:03
  6 * @: Author:    Alimy
  7 *******************************************************/
  8 
  9 /*******************************************************
 10 * @: 头文件包含
 11 *******************************************************/
 12 #include "link_list.h"
 13 #include <stdio.h>
 14 #include <conio.h>   
 15 #include <stdlib.h> 
 16 
 17 
 18 /*******************************************************
 19 * @:(外部&内部)变量声明及定义
 20 *******************************************************/
 21 
 22 /*******************************************************
 23 * @: (外部&内部)函数声明及定义
 24 *******************************************************/
 25 void printmenu(void);
 26 
 27 
 28 /*******************************************************
 29 * @: 主函数
 30 *******************************************************/
 31 int main(){
 32     pLinkList   LinkList_Display = NULL;
 33     unsigned char keyValue = 0;
 34     int idx = 0;
 35     ElemType e = 0;
 36     if(OK!=CreateList_L(&LinkList_Display,5))
 37         goto _end;
 38     
 39     while(1){
 40         system("cls");
 41         printmenu();
 42         fflush(stdin);
 43         scanf("%c",&keyValue);
 44         fflush(stdin);
 45         switch(keyValue){
 46             case 'a':
 47                 printf("请输入你要插入的位置索引及要插入的数据
");
 48                 scanf("%d%d",&idx,&e);
 49                 printf("你要插入数据的位置是 【%d】,要插入的数据是【%d】
",idx,e);
 50                 InsertElem_L(&LinkList_Display,idx,e);
 51                 printf("按任意键返回主菜单
"); 
 52                 getch();
 53                 break;
 54             
 55             case 'b':
 56                 printf("请输入你要删除单链表中的元素的索引
");
 57                 scanf("%d",&idx);
 58                 printf("你要删除数据的位置是 【%d】
",idx);
 59                 if(OK==DeleteElem_L(&LinkList_Display,idx,&e)){
 60                     printf("删除元素成功,被删除的元素值为 %d 
",e);
 61                 }
 62                 printf("按任意键返回主菜单
"); 
 63                 getch();
 64                 break;
 65             case 'c':
 66                 printf("请输入你要得到单链表中的元素的索引
");
 67                 scanf("%d",&idx);
 68                 if(OK!=GetElem_L(&LinkList_Display,idx,&e)){
 69                     printf("获取元素失败,请检查相关输入是否符合操作条件
");
 70                     }
 71                 else{
 72                     printf("获取到的元素是 %d 
",e);
 73                     }
 74                 printf("按任意键返回主菜单
"); 
 75                 getch();
 76                 break;
 77             case 'd':
 78                 printf("请输入你要定位单链表中的元素值
");
 79                 scanf("%d",&e);
 80                 LocateElem_L(&LinkList_Display,e);
 81                 printf("按任意键返回主菜单
"); 
 82                 getch();
 83                 break;
 84             case 'e':
 85                 idx = GetLength_L(&LinkList_Display);
 86                 if(LinkList_Display->p_next!=NULL){
 87                     printf("当前表长为【%d】 
", idx);
 88                 }
 89                 printf("按任意键返回主菜单
"); 
 90                 getch();
 91                 break;
 92             case 'f':
 93                 ClearList_L(&LinkList_Display);
 94                 printf("清除单链表完成,按任意键返回主菜单
"); 
 95                 getch();
 96                 break;
 97             case 'g':
 98                 DisplayList_L(&LinkList_Display);
 99                 printf("按任意键返回主菜单
"); 
100                 getch();
101                 break;
102             case 'h':
103                 goto _end;
104                 break;
105             default:
106                 printf("你的输入环节有误,清重新输入 
");
107                 printf("按任意键返回主菜单
"); 
108                 getch();
109                 break;
110         }
111     }
112 
113     
114 
115 _end:
116     ClearList_L(&LinkList_Display);      // 释放堆空间
117     if(LinkList_Display!=NULL)
118         free(LinkList_Display); //释放头结点
119 /*
120 
121 错误代码 :
122     while(LinkList_Display!=NULL)
123         free(LinkList_Display);
124         
125 //刚刚才知道 free(p)之后p还是原来的数,不会变成NULL
126 研究了一下 p自身虽然是指针,但不能通过指针的值并不能改变自身的值,所以说传地址能改变原元素的值是有条件的
127 再者,传值就一定改变不了原元素的 值么
128 
129 //另外一个测试代码,VC6下测试结果符合预期,其他编译器未经测试
130 // test -- start
131 #include <stdio.h>
132 void changedata(long int pointer){
133     *((int *)pointer) = 100;
134     return ;
135 
136 }
137 int main(void){
138     int temp = 1000;
139     long    int p = (long int)(&temp);  // 在VC6中long int为四个字长,等于指针长度
140     printf("temp = %d 
",temp);
141     changedata(p);
142     printf("temp = %d 
",temp);
143     return 1;
144 }
145 // test--end
146 传值还是传址不能被形式表象所迷惑。
147 */
148     getch();
149     return 0;    
150 
151 }
152 
153 
154 /*
155 *@: 打印演示主菜单
156 *@:返回值(无)
157 */
158 void printmenu(void){
159     printf("  【主菜单】: 请输入数据相应对应的操作
");
160     printf("【a】: 在单链表中插入元素
");
161     printf("【b】: 在单链表中删除元素
");
162     printf("【c】: 在单链表中得到元素
");
163     printf("【d】: 在单链表中定位元素
");
164     printf("【e】: 获取当前单链表的表长
");
165     printf("【f】: 清除单链表,整表删除
");
166     printf("【g】: 打印当前单链表的所有数据
");
167     printf("【h】: 退出当前程序
");
168     printf(" 您需要执行的操作项是:  ");
169 }
170 
171 
172 
173 /*
174 
175 单链表结构与顺序表存储结构的比较
176     1:存储分配方式
177         顺序表:申请连续块空间
178         单链表:链式申请,存储单元任意
179     2:时间性能
180         查找:
181             顺序表:O(1)
182             单链表:O(n)
183         删除&插入:
184             顺序表:O(n)
185             单链表:第一次为O(n),后续为O(1)
186     3:空间性能
187         顺序表:
188             需要预分配,分配大了造成浪费;分配小了,容易造成溢出
189         单链表:
190             只要    有,随时可以用
191             
192             
193 若线性表需要频繁的查找,很少进行插入&删除操作,宜采用顺序存储结构
194 反之可以采用链式存储结构
195 
196 
197 例子:
198 游戏开发中,对于用户注册注册的个人信息,只读取居多,宜采用顺序存储结构
199 游戏中的武器或者装备列表,增加删除操作更多,宜采用链式存储结构
200 
201 
202 当线性表中的元素个数变化大或者对应用不了解的情况下,最好采用单链表结构,不必考虑存储空间的大小问题。
203 若评估知道规模大致长度,可以用顺序表。。
204 
205 总之:综合各种条件考虑!
206 */
main.c

(老实说,我对单链表的头结点有点好奇,

我的想法是为头结点单独管理,然后让头结点的数据域来管理单链表的长度。。。这样在插入&删除等操作中,直接就可以用头结点的数据域来判断是否能完成插入&删除等操作了。。

1 typedef struct LHead{ //头结点,其实和 LNode的内存结构相似,
2  int LinkListLength; //数据域,可以存储当前线性表的长度,也可以什么也不存储
3  struct LNode *p_FirstNode; //指针域指向线性表的第一个元素
4 }LHead, *pLHead;

额。静态链表&(循环链表&双向链表)就直接跳过了,不写demo了。。

静态链表不是在拥有指针机制的其他高级语言使用链表的机制。

循环链表&双向链表和单链表的实现类似。

~不再更新,都不让我写公式,博客园太拉胯了
原文地址:https://www.cnblogs.com/alimy/p/3361977.html