zoukankan      html  css  js  c++  java
  • [数据结构与算法] 单链表的简单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了。。

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

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

    ~不再更新,都不让我写公式,博客园太拉胯了
  • 相关阅读:
    jQuery scroll事件
    jquery offset() 与position()方法的区别
    股票基本知识
    swfObject 使用说明
    javascript和swf在网页中交互的一些总结
    TCP 同步传输:客户端发送,服务器段接收
    读取Excel
    sql 执行顺序
    支付宝及时到帐接口
    Ajax中get提交和post提交的区别
  • 原文地址:https://www.cnblogs.com/alimy/p/3361977.html
Copyright © 2011-2022 走看看