zoukankan      html  css  js  c++  java
  • 链表的基本操作

    2013-08-17 16:26:51

    再次写链表的基本操作,包括前插法创建链表、链表的插入、删除、排序、翻转、显示、销毁。

    此次写的链表时带有头指针的,是否有头指针,对于链表的各个操作都会有影响,与之前写的不带头指针的链表相比,确实方便很多,不易出错。

    小结:

    1. 对于带有头结点的链表,空链表(pHead->next= NULL)与头指针为NULL的链表(pHead = NULL)是不同的,后者是非法的链表,要当做异常处理;
    2. 函数入口对于异常输入的处理,比如下面代码中多个函数中的assert(pHead != NULL);排除了链表头结点为空的异常情况;
    3. 函数对于特殊输入的处理,比如插入、删除的位置大于链表长度,以及链表为空的处理;链表翻转时链表长度为空或1时直接返回即可;在函数开始时最好就对这些特殊的输入进行处理,以免遗漏;注意插入、删除的是第一个以及最后一个的情况
    4. 存放插入、删除的位置、链表长度的变量为size_t类型的,排除了非法的负数的情况,但也要注意这种做法带来的副作用,就是对于size_t类型的变量0-1的结果为最大的正数,而非负数,判断循环结束时,应注意到这个问题。
    5. 输入ctrl+z结束键盘输入后,要想再次从键盘接收输入,必须用cin.clear();  cin.sync();清楚流,否则不能接收输入

    下面是完整的代码(包括测试):

      1 #include <iostream>
      2 #include <cassert>
      3 using namespace std;
      4 
      5 typedef int DataType;  //链表元素类型
      6 
      7 typedef struct node    //链表结点
      8 {
      9     DataType data;
     10     node *next;
     11 
     12 }LNode,*PLNode;
     13 
     14 //创建带有头结点的链表
     15 //输入ctrl+z结束
     16 //有无头结点将会影响到对链表的所有操作,包括显示链表元素、插入、删除、销毁等
     17 PLNode CreatLink()
     18 {
     19     PLNode pHead = new LNode;  //注意delete
     20     PLNode pPre = pHead;
     21     PLNode pCur = NULL;
     22     pHead->data = 0;        //空头
     23     pHead->next = pCur;
     24 
     25     DataType dataTmp = 0;
     26 
     27     cout<<"Please enter the elements of the link  ,separate with space,and end with ctrl+z :"<<endl;
     28     while (cin>>dataTmp)
     29     {
     30         pCur = new LNode;
     31         pCur->data = dataTmp;
     32         pCur->next = NULL;
     33 
     34         pPre->next = pCur;
     35         pPre = pCur;
     36     }
     37 
     38     return pHead;
     39 }
     40 
     41 //创建不带头结点的链表
     42 //输入ctrl+z结束
     43 PLNode CreatLinkWithNonNullHead()
     44 {
     45     PLNode pHead = NULL;  //delete
     46     PLNode pPre = NULL;
     47     PLNode pCur = NULL;
     48     
     49     DataType dataTmp = 0;
     50 
     51     cout<<"Please enter the elements of the link  ,separate with space,and end with ctrl+z :"<<endl;
     52     while (cin>>dataTmp)
     53     {
     54         pCur = new LNode;
     55         pCur->data = dataTmp;
     56         pCur->next = NULL;
     57 
     58         if (NULL == pHead)   //对头的特别处理
     59         {
     60             pHead = pCur;
     61             pPre = pCur;
     62         }
     63         else
     64         {
     65             pPre->next = pCur;
     66         }
     67         pPre = pCur;
     68     }
     69     return pHead;
     70 }
     71 
     72 //对头结点为pHead的链表,在位置posToInsert处插入元素dataToInsert
     73 //posToInsert定义为size_t类型,排除了位置为负数的异常输入
     74 //注意对输入位置超过链表长度的处理
     75 PLNode InsertLink(PLNode &pHead,size_t posToInsert,const DataType dataToInsert)
     76 {
     77     assert(pHead != NULL);
     78 
     79     PLNode pCur = pHead;
     80     PLNode pNew = new LNode;
     81     pNew->data = dataToInsert;
     82     pNew->next = NULL;
     83 
     84     while (posToInsert--)
     85     {
     86         //assert(pCur != NULL);  //保证不超过链表长度
     87         pCur = pCur->next;
     88         assert(pCur != NULL);  //保证不超过链表长度,放在前面当posToInsert减到0时会出错
     89     }
     90 
     91     pNew->next = pCur->next;
     92     pCur->next = pNew;
     93 
     94     return pHead;
     95 }
     96 
     97 //删除结点指针指向的元素,未测试
     98 PLNode InsertLinkAtNode(PLNode &pHead,const PLNode pPosToInsert,const DataType dataToInsert)
     99 {
    100     assert(pHead != NULL);
    101 
    102     PLNode pCur = pHead;
    103     PLNode pNew = new LNode;
    104     pNew->data = dataToInsert;
    105     pNew->next = NULL;
    106 
    107     while (pCur != pPosToInsert)
    108     {
    109         assert(pCur != NULL);  //保证不超过链表长度
    110         pCur = pCur->next;
    111     }
    112 
    113     pNew->next = pCur->next;
    114     pCur->next = pNew;
    115 
    116     return pHead;
    117 }
    118 
    119 //对头结点为pHead的链表,在位置posToInsert处插入元素dataToInsert
    120 //posToInsert定义为size_t类型,排除了位置为负数的异常输入
    121 //注意对输入位置超过链表长度的处理
    122 PLNode DeleteLink(PLNode &pHead,size_t posToDelete)
    123 {
    124     assert(pHead != NULL);
    125 
    126     if (0 == posToDelete)
    127     {
    128         return pHead;
    129     }
    130 
    131     PLNode pCur = pHead;
    132     PLNode pNodeToDelete = NULL;
    133     size_t posPriorToDelete = posToDelete - 1;
    134 
    135     while (posPriorToDelete--)
    136     {
    137         pCur = pCur->next;
    138         assert(pCur != NULL);  //保证不超过链表长度,放在前面当posToInsert减到0时会出错
    139     }
    140 
    141     pNodeToDelete = pCur->next;
    142     assert(pNodeToDelete != NULL);  ////保证不超过链表长度
    143     pCur->next = pNodeToDelete->next;
    144     delete pNodeToDelete;
    145     return pHead;
    146 }
    147 
    148 //获取链表长度
    149 size_t GetLengthOfLink(PLNode pHead)
    150 {
    151     assert(NULL != pHead);
    152 
    153     size_t lengthOfLink = 0;
    154     PLNode pCur = pHead;
    155 
    156     while (NULL != pCur->next)
    157     {
    158         ++lengthOfLink;
    159         pCur = pCur->next;
    160     }
    161 
    162     return lengthOfLink;
    163 }
    164 
    165 //冒泡法最链表元素排序
    166 PLNode BubbleSortLink(PLNode &pHead)
    167 {
    168     assert(NULL != pHead);
    169     
    170     PLNode pCur = pHead->next;
    171     
    172     size_t lengthOfLink = GetLengthOfLink(pHead);  
    173     size_t tmp = 0;
    174     int i = (int)lengthOfLink; //定义为int型,在lengthOfLink为0时,lengthOfLink--为-1
    175     int j = 0;
    176 
    177     while (i-- > 1)
    178     {
    179         pCur = pHead->next;  //每次都指向第一个结点
    180         j = i;
    181         /*while (j--)*/
    182         while (j-- > 0)
    183         {
    184             if (pCur->data > pCur->next->data)
    185             {
    186                 tmp = pCur->data;
    187                 pCur->data = pCur->next->data;
    188                 pCur->next->data = tmp;
    189             }
    190 
    191             pCur = pCur->next;
    192         }
    193     }
    194     return pHead;
    195 }
    196 
    197 //链表元素翻转
    198 PLNode ReverseLink(PLNode &pHead)
    199 {
    200     assert(NULL != pHead);
    201 
    202     if (NULL == pHead->next || NULL == pHead->next->next)  //短路求值的特性保证pHead->next->next不会因为pHead->next == NULL而非法操作
    203     {
    204         return pHead;
    205     }
    206     
    207     PLNode pPre = pHead->next;  //上面的if保证此处的访问都是合法的
    208     PLNode pCur = pPre->next;
    209     PLNode pNxt = NULL;
    210 
    211     pPre->next = NULL;  //此时pPre为翻转后链表的最后一个结点,将next置为NULL
    212 
    213     while (pCur != NULL)
    214     {
    215         pNxt = pCur->next;
    216         pCur->next = pPre;  //指正方向翻转
    217 
    218         pPre = pCur;
    219         pCur = pNxt;
    220     }
    221 
    222     //pHead = pPre;
    223     pHead->next = pPre;
    224     return pHead;
    225 }
    226 
    227 //显示有头结点的链表的元素
    228 void Displaylink(const PLNode &pHead)
    229 {
    230     assert(pHead != NULL);
    231     PLNode pCur = pHead->next;
    232     while (pCur != NULL)
    233     {
    234         cout<<pCur->data<<"	";
    235         pCur = pCur->next;
    236     }
    237     cout<<endl;
    238 }
    239 
    240 //显示没有头结点的链表的元素
    241 void DisplaylinkWithNonNullHead(const PLNode &pHead)
    242 {
    243     PLNode pCur = pHead;
    244     while (pCur != NULL)
    245     {
    246         cout<<pCur->data<<"	";
    247         pCur = pCur->next;
    248     }
    249     cout<<endl;
    250 }
    251 
    252 //带有头结点的链表的销毁
    253 void Destorylink(PLNode &pHead)
    254 {
    255     assert(pHead != NULL);
    256     PLNode pCur = pHead->next;
    257     while (pCur != NULL)
    258     {
    259         delete pHead;    //删除头结点
    260         pHead = pCur;
    261         pCur = pCur->next;
    262     }
    263 }
    264 
    265 //测试链表操作
    266 //除了作为比较的建立链表操作,链表的所有操作都基于带有头结点的链表
    267 //因为带有头结点的链表在各种操作上都会比较方便
    268 void Testlink()
    269 {
    270     PLNode pHead = NULL;
    271 
    272     //Test CreatLinkWithNullHead...
    273     cout<<"Test CreatLink..."<<endl;
    274     pHead = CreatLink();
    275     cout<<"display the link created by CreatLink : "<<endl;
    276     Displaylink(pHead);
    277     
    278     cin.clear();  //清除流状态
    279     cin.sync();
    280 
    281     //Test InsertLink...
    282     /*size_t posToInsert = 0;
    283     DataType dataToInsert = 0;
    284 
    285     cout<<"Please enter the position and the data to insert,end with ctrl+z :"<<endl;
    286     while (cin>>posToInsert>>dataToInsert)
    287     {
    288         cout<<"The link before insertion : "<<endl;
    289         Displaylink(pHead);
    290 
    291         pHead = InsertLink(pHead,posToInsert,dataToInsert);
    292 
    293         cout<<"The link after insertion : "<<endl;
    294         Displaylink(pHead);
    295 
    296         cout<<"Please enter the position to insert,end with ctrl+z :"<<endl;
    297     }
    298     cin.clear();  //清除流状态
    299     cin.sync();*/
    300 
    301     //Test DeleteLink...
    302     //size_t posToDelete = 0;
    303     //
    304     //cout<<"Please enter the position to delete,end with ctrl+z :"<<endl;
    305     //while (cin>>posToDelete)
    306     //{
    307     //    cout<<"The link before insertion : "<<endl;
    308     //    Displaylink(pHead);
    309 
    310     //    pHead = DeleteLink(pHead,posToDelete);
    311 
    312     //    cout<<"The link after delete : "<<endl;
    313     //    Displaylink(pHead);
    314 
    315     //    cout<<"Please enter the position to delete,end with ctrl+z :"<<endl;
    316     //}
    317 
    318     //cin.clear();  //清除流状态
    319     //cin.sync();
    320 
    321     //Test GetLengthOfLink...
    322 
    323     //size_t lengthOfLink = GetLengthOfLink(pHead);
    324     cout<<"Test GetLengthOfLink..."<<endl;
    325     cout<<"the length of link is : "<<GetLengthOfLink(pHead)<<endl;
    326 
    327     //Test BubbleSortLink...
    328     cout<<"Test BubbleSortLink..."<<endl;
    329     BubbleSortLink(pHead);
    330     cout<<"The link after sort : "<<endl;
    331     Displaylink(pHead);
    332 
    333     //Test BubbleSortLink...
    334     cout<<"Test ReverseLink..."<<endl;
    335     ReverseLink(pHead);
    336     cout<<"The link after reverse : "<<endl;
    337     Displaylink(pHead);
    338 
    339     Destorylink(pHead);
    340 
    341     /*cout<<"Test CreatLinkWithNonNullHead..."<<endl;
    342     pHead = CreatLinkWithNonNullHead();
    343     cout<<"display the link created by CreatLinkWithNullHead : "<<endl;
    344     DisplaylinkWithNonNullHead(pHead);
    345     Destorylink(pHead);*/
    346 
    347 }
    348 
    349 //main
    350 int main()
    351 {
    352     Testlink();
    353     return 0;
    354 }
  • 相关阅读:
    java keytool证书工具使用小结(转)
    Https socket 代理
    SSL连接出现的问题
    Https 代理 sslsocket
    Https socket 连接
    linux系统一键安装phpstudy的lnmp环境
    Yii2框架实现计数器功能
    yii2框架增删改查案例
    yii2框架原生的结合框架使用的图片上传
    php将抓取的图片链接下载到本地
  • 原文地址:https://www.cnblogs.com/youngforever/p/3264795.html
Copyright © 2011-2022 走看看