• 常用链表操作总结


    --常用链表操作总结--(转)

    1. 求单链表中结点的个数
    2. 将单链表反转
    3. 查找单链表中的倒数第K个结点(k > 0)
    4. 查找单链表的中间结点
    5. 从尾到头打印单链表
    6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序
    7. 判断一个单链表中是否有环
    8. 判断两个单链表是否相交
    9. 求两个单链表相交的第一个节点
    10. 已知一个单链表中存在环,求进入环中的第一个节点
    11. 给出一单链表头指针pHead和一节点指针pToBeDeleted,O(1)时间复杂度删除节点pToBeDeleted

      1 /****************************************
      2 * File Name: l1.cpp
      3 * Author: sky0917
      4 * Created Time: 2014年01月11日 21:50:22
      5 ****************************************/
      6 #include <map>
      7 #include <cmath>
      8 #include <queue>
      9 #include <stack>
     10 #include <cstdio>
     11 #include <cstring>
     12 #include <algorithm>
     13 using namespace std;
     14 
     15 struct Node{
     16     int key;
     17     Node *next;
     18     Node(){
     19         key = 0;
     20         next = NULL;
     21     }
     22 };
     23 
     24 // 1. 求单链表中节点的个数 
     25 int getListLength(Node *head){     
     26 
     27     if (head->next == NULL) 
     28         return 0;
     29     int ListLength = 0;
     30     Node *p = head->next;
     31     while (p != NULL){
     32         ListLength++;
     33         p = p->next;
     34     }
     35 
     36     return ListLength;
     37 }
     38 
     39 // 2. 将单链表反转
     40 void reverseList(Node *head){
     41 
     42     if (head->next == NULL)
     43         return;    
     44 
     45     Node *p1, *p2, *p3;
     46 
     47     p2 = head->next;
     48     if (p2->next == NULL)//只有一个元素,直接返回
     49         return;    
     50     
     51     p1 = p2->next;
     52     p2->next = NULL;
     53 
     54     while (p1 != NULL){
     55         p3 = p1->next;
     56         p1->next = p2;
     57         p2 = p1;
     58         p1 = p3;
     59     }    
     60     head->next = p2;
     61 }
     62 
     63 // 3. 查找单链表中的倒数第K个结点(k > 0)
     64 int GetRkthNode(Node *head, int k){
     65 
     66     Node *pf = head;
     67     if (NULL == pf->next)
     68         return -1;
     69     if (k <= 0)
     70         return -1;
     71 
     72     int tot = 0;
     73     while (pf->next != NULL){
     74         tot++;
     75         pf = pf->next;    
     76         if (tot == k) break;
     77     }
     78     if (tot < k) return -1;
     79     
     80     Node *pr = head->next;
     81     while (pf->next != NULL){
     82         pf = pf->next;
     83         pr = pr->next;    
     84     }    
     85     return pr->key;
     86 }
     87 
     88 // 4. 查找单链表的中间结点
     89 Node* getMidNode(Node *head){
     90 
     91     Node *pf = head->next;
     92     if (pf == NULL)
     93         return head;
     94 
     95     if (pf->next == NULL)
     96         return pf;
     97 
     98     Node *pr = head->next;
     99     while (pf->next != NULL){
    100         pf = pf->next;
    101         pr = pr->next;    
    102         if (pf->next != NULL){
    103             pf = pf->next;
    104         }
    105     }
    106     return pr;
    107 }
    108 
    109 // 5. 从尾到头打印单链表
    110 void rPrintList(Node *head){
    111 
    112     stack<Node *> s;
    113     Node *p = head;
    114     
    115     if (p->next == NULL)
    116         return;
    117     
    118     while (p->next != NULL){
    119         s.push(p->next);
    120         p = p->next;    
    121     }
    122     
    123     while (!s.empty()){
    124         p = s.top();
    125         printf("%d->",p->key);
    126         s.pop();
    127     }
    128     puts("");
    129 }
    130 
    131 // 5. 从尾到头打印单链表(2)
    132 void dfsPrint(Node *p){
    133 
    134     if (p == NULL)
    135         return;
    136     
    137     dfsPrint(p->next);
    138     printf("%d->",p->key);
    139 
    140 }
    141 void rPrintList2(Node *head){
    142 
    143     Node *p = head;
    144 
    145     if (p->next == NULL)
    146         return;
    147      
    148     dfsPrint(p->next);
    149     puts("");
    150 }
    151 
    152 // 6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序
    153 Node *mergeSortedList(Node *head, Node *head2){
    154 
    155     Node *p1 = head->next;
    156     Node *p2 = head2->next;
    157 
    158     if (p1 == NULL)
    159         return head2;
    160     if (p2 == NULL)
    161         return head;
    162         
    163     Node *mHead = NULL;
    164     if (p1->key < p2->key){
    165         mHead = head;
    166         mHead->next = NULL;
    167     }
    168     else{
    169         mHead = head2;
    170         mHead->next = NULL;
    171     }    
    172 
    173     Node *pm = mHead;
    174     while (p1 != NULL && p2 != NULL){
    175         if (p1->key < p2->key){
    176             pm->next = p1;
    177             p1 = p1->next;
    178             pm = pm->next;
    179             pm->next = NULL;            
    180         }
    181         else{
    182             pm->next = p2;
    183             p2 = p2->next;
    184             pm = pm->next;
    185             pm->next == NULL;
    186         }
    187     }
    188 
    189     while (p1 != NULL){
    190         pm->next = p1;
    191         p1 = p1->next;
    192         pm = pm->next;
    193         pm->next = NULL;
    194     }
    195     while (p2 != NULL){
    196         pm->next = p2;
    197         p2 = p2->next;
    198         pm = pm->next;
    199         pm->next = NULL;
    200     }
    201     return mHead;
    202 }
    203 
    204 // 7. 判断一个单链表中是否有环
    205 bool hasCircle(Node *head){
    206 
    207     if (head == NULL) 
    208         return false;
    209 
    210     Node *pFast = head->next;
    211     Node *pSlow = head->next;
    212     
    213     while (pFast != NULL && pFast->next != NULL){
    214         pFast = pFast->next->next;
    215         pSlow = pSlow->next;
    216         if (pSlow == pFast)
    217             return true;
    218     }
    219     return false;
    220 }
    221 
    222 // 8. 判断两个单链表是否相交
    223 bool isIntersect(Node *head1, Node *head2){
    224     
    225     if (head1 == NULL || head2 == NULL)
    226         return false;
    227 
    228     Node *p1 = head1;
    229     while (p1->next != NULL){
    230         p1 = p1->next;
    231     }    
    232 
    233     Node *p2 = head2;
    234     while (p2->next != NULL){
    235         p2 = p2->next;
    236     }
    237     
    238     return p1 == p2;
    239 }
    240       
    241 // 9. 求两个单链表相交的第一个节点
    242 Node *getFirstCommonNode(Node *head1, Node *head2){
    243     
    244     if (head1 == NULL || head2 == NULL)
    245         return NULL;
    246 
    247     int len1 = 0;
    248     Node *p1 = head1;
    249     while (p1->next != NULL){
    250         p1 = p1->next;
    251         len1++;
    252     }
    253 
    254     int len2 = 0;
    255     Node *p2 = head2;
    256     while (p2->next != NULL){
    257         p2 = p2->next;
    258         len2++;
    259     }
    260      
    261     if (p1 != p2) 
    262         return NULL;
    263     
    264     p1 = head1;
    265     p2 = head2;
    266     
    267     if (len1 > len2){
    268         int k = len1 - len2;
    269         while (k--){
    270             p1 = p1->next;
    271         }
    272     }
    273     else{
    274         int k = len2 - len1;
    275         while (k--){
    276             p2 = p2->next;
    277         }
    278     }
    279     while (p1 != p2){
    280         p1 = p1->next;
    281         p2 = p2->next;
    282     }
    283     return p1;
    284 }
    285 
    286 // 10. 已知一个单链表中存在环,求进入环中的第一个节点
    287 Node *getFirstNodeInCircle(Node *head){
    288     
    289     if (head == NULL || head->next == NULL)
    290         return NULL;
    291      
    292     Node *pFast = head;
    293     Node *pSlow = head;
    294     while (pFast != NULL && pFast->next != NULL){
    295         pFast = pFast->next->next;
    296         pSlow = pSlow->next;
    297         if (pFast == pSlow)
    298             break;
    299     }
    300     if (pFast == NULL || pFast->next == NULL)
    301         return NULL;
    302     
    303     Node *ptmp = pSlow;
    304     Node *ph1 = head->next;
    305     Node *ph2 = ptmp->next;
    306     
    307     int len1 = 0;
    308     Node *p1 = ph1;
    309     while (p1 != ptmp){
    310         p1 = p1->next;
    311         len1++;
    312     }
    313     
    314     int len2 = 0;
    315     Node *p2 = ph2;
    316     while (p2 != ptmp){
    317         p2 = p2->next;
    318         len2++;
    319     }    
    320 
    321     p1 = ph1;
    322     p2 = ph2;
    323     
    324     if (len1 > len2){
    325         int k = len1 - len2;
    326         while (k--){
    327             p1 = p1->next;
    328         }
    329     }
    330     else{
    331         int k = len2 - len1;
    332         while (k--){
    333             p2 = p2->next;
    334         }
    335     }
    336     while (p1 != p2){
    337         p1 = p1->next;
    338         p2 = p2->next;    
    339     }
    340     return p1;
    341 }
    342 
    343 // 11. 给出一单链表头指针pHead和一节点指针pToBeDeleted,O(1)时间复杂度删除节点pToBeDeleted
    344 void deleteNode(Node *head, Node *pd){
    345     
    346     if (head == NULL || pd == NULL)
    347         return;
    348     
    349     if (pd->next != NULL){
    350         pd->key = pd->next->key;
    351         Node *ptmp = pd->next;
    352         pd->next = pd->next->next;
    353         delete ptmp;
    354     }
    355     else{
    356         Node *p = head;
    357         while (p->next != pd){
    358             p = p->next;
    359         }
    360         p->next = NULL;
    361         delete pd;    
    362     }
    363 }
    364 
    365 int main(){
    366 
    367     void init(Node *head); 
    368     void print(Node *head);
    369     Node *head = new Node();
    370 
    371     init(head);    
    372     print(head);
    373 
    374     /*
    375      * @求单链表中节点的个数
    376      */
    377     int len = getListLength(head); 
    378     printf("len = %d
    ",len);    
    379 
    380     /* 
    381      * @将单链表反转
    382      */
    383     reverseList(head); 
    384     print(head);
    385 
    386     /* 
    387      * @将单链表反转
    388      */
    389     reverseList(head);  
    390     print(head); 
    391 
    392     /*
    393      *@ 返回链表的倒数第 k 个元素的值
    394      *  用两个指针,让第一个指针先走k个元素,然后第二个指针和第一个指针一起走,
    395      *  但第一个指针走到尾部的时候,第二个就走到了倒数第k个元素的位置
    396      */
    397     int kth = GetRkthNode(head, 5);
    398     printf("kth = %d
    ",kth);
    399 
    400     /*
    401      * @查找单链表的中间结点
    402      * 设置两个指针,两个指针同时向前走,前面的指针每次走两步,后面的指针每次走一步,
    403      * 前面的指针走到最后一个结点时,后面的指针所指结点就是中间结点,即第(n/2+1)个
    404      * 结点
    405      * 时间复杂度 O(n)
    406      */ 
    407     Node *midNode = getMidNode(head);    
    408     printf("midNode.val = %d
    ",midNode->key);
    409 
    410     /*
    411      * @从尾到头打印单链表
    412      *  两种方式:一个是自己模拟栈,另一种是调用系统栈
    413      *  时间复杂度 O(n)
    414      */
    415     rPrintList(head);        
    416     rPrintList2(head);
    417 
    418     /*
    419      *@已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序
    420      * 类似归并排序。
    421      * 注意两个链表都为空,和其中一个为空时的情况。
    422      * O(1)的空间,时间复杂度为O(max(len1, len2))。
    423      */
    424     Node *head2 = new Node();
    425     init(head2);
    426     Node *mhead = mergeSortedList(head, head2);
    427     print(mhead);    
    428 
    429     /*
    430      * @判断一个单链表中是否有环
    431      * 用两个指针,一个指针一次走两步,一个指针一次走一步,如果有环,两个指针肯定会在环中相遇。
    432      * 时间复杂度为O(n)
    433      */
    434 //    mhead->next->next->next = mhead->next;
    435     if (hasCircle(mhead))
    436         printf("有环
    ");
    437     else printf("无环
    ");    
    438     
    439     /*
    440      * @判断两个单链表是否相交鱼某一点
    441      *  如果两个链表相交鱼某一点,那么在这个相交节点之后的所有节点都是两个链表所共有的。
    442      *  所以如果相交那么最后一个节点一定是共有的。
    443      *  可以先遍历第一个链表记住最后一个节点,然后遍历第二个链表,到最后一个节点时和第一
    444      *  个链表的最后一个节点比较,如果相同,则相交,否则不相交。
    445      *  时间复杂度O(len1+len2) 空间复杂度为O(1)
    446      */    
    447      
    448      if (isIntersect(head, mhead))
    449          printf("相交
    ");
    450      else printf("不相交
    ");
    451     
    452      /*
    453       * @求两个单链表相交的第一个节点
    454       * 先遍历第一个单链表,计算其长度len1, 同时保存最后一个节点的地址
    455       * 再遍历第二个单链表,计算其长度len2, 同时查看最后一个节点是否和第一个链表的最后
    456       * 一个节点相同,如果不相同,说明不想交,直接返回。
    457       * 再次从头遍历两个链表,如果len1 > len2,那么第一个链表先遍历Len1-len2个节点,这个
    458       * 时候两个链表当前节点距离第一个相交节点的距离相同,只要一起遍历,直到两个节点的
    459       * 地址相同即可。
    460       * 时间复杂度O(len1+len2)
    461       */
    462       Node *pt = getFirstCommonNode(head, mhead);
    463       if (pt != NULL)
    464           printf("FirstCommonNode's value is %d
    ",pt->key);
    465       else printf("No intersect
    "); 
    466 
    467      /*
    468       * @已知一个单链表有环,求进入环中的第一个节点
    469       *  首先判断是否存在环,如果没有环直接返回。
    470       *  在环中的一个节点处断开(函数结束之后需要恢复原来的链表结构)
    471       *  然后就转化成了求两个单链表第一个相交节点的问题。
    472       *  
    473       */
    474        //mhead->next->next->next->next->next = mhead->next->next->next;
    475       Node *pF = getFirstNodeInCircle(mhead);
    476       if (pF != NULL)
    477           printf("The first Node in circle's value = %d
    ",pF->key);
    478       else printf("No circle
    ");
    479 
    480      /*
    481       * @给出一个单链表头指针head,和一个节点指针pToBeDeleted
    482       *  要求用O(1)的时间爱你复杂度删除节点pToBeDeleted
    483       *  可以把要删除的节点的下一个节点的数据复制到该节点,然后删除
    484       *  下一个节点即可。
    485       *  注意最后后一个节点的情况。这个时候只能用普通的方法来找到前一个节点。
    486       */
    487     
    488       Node *pd = mhead->next->next->next;      
    489       deleteNode(mhead, pd);
    490       print(mhead); 
    491     return 0;
    492 }
    493 
    494 void init(Node *head){
    495     Node *p = head;
    496     
    497     for (int i=0; i<5; i++){
    498         p->next = new Node();
    499         p->next->key = i+1;
    500         p = p->next;
    501     }
    502 }
    503 
    504 void print(Node *head){
    505     if (head->next == NULL)
    506         return;
    507     Node *p = head->next;
    508     while (p != NULL){
    509         printf("%d --> ",p->key);
    510         p = p->next;
    511     }
    512     
    513     puts("");
    514 }
  • 相关阅读:
    设置跨域
    Vs自定nuget push菜单
    VS IIS Express 支持局域网访问
    字符串GZIP压缩解压
    C# 使用 protobuf 进行对象序列化与反序列化
    RabbitMQ
    如果调用.net core Web API不能发送PUT/DELETE请求怎么办?
    log4net配置使用
    redis实现消息队列
    Error-the resource is not on the build path of a java project
  • 原文地址:https://www.cnblogs.com/sky0917/p/3527505.html
Copyright © 2020-2023  润新知