zoukankan      html  css  js  c++  java
  • 常用链表操作总结

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

    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 }
  • 相关阅读:
    668. Kth Smallest Number in Multiplication Table
    658. Find K Closest Elements
    483. Smallest Good Base
    475. Heaters
    454. 4Sum II
    441. Arranging Coins
    436. Find Right Interval
    410. Split Array Largest Sum
    392. Is Subsequence
    378. Kth Smallest Element in a Sorted Matrix
  • 原文地址:https://www.cnblogs.com/sky0917/p/3527505.html
Copyright © 2011-2022 走看看