链表题目总结

题目.单链表的反序

 

//逆转链表,并返回逆转后的头节点   
  1. node* reverse(node *head)  
  2. {  
  3.     if(head == NULL || head->next == NULL)  
  4.     {  
  5.         return head;  
  6.     }  
  7.     node *cur = head;  
  8.     node *pre = NULL;  
  9.     node *tmp;  
  10.     while(cur->next)  
  11.     {  
  12.         tmp = pre;  
  13.         pre = cur;  
  14.         cur = cur->next;  
  15.         pre->next = tmp;                  //操作pre的next逆转   
  16.     }  
  17.     cur->next = pre;                     //结束时,操作cur的next逆转   
  18.     return cur;  
  19. }  

 

//逆转链表,并返回逆转后的头节点 node* reverse(node *head) { if(head == NULL || head->next == NULL) { return head; } node *cur = head; node *pre = NULL; node *tmp; while(cur->next) { tmp = pre; pre = cur; cur = cur->next; pre->next = tmp; //操作pre的next逆转 } cur->next = pre; //结束时,操作cur的next逆转 return cur; }

 

 

 

 

 

题目.给单链表建环

 

 //给单链表建环,让尾指针,指向第num个节点,若没有,返回false   

  1. bool bulid_looplink(node *head, int num)  
  2. {  
  3.     node *cur = head;  
  4.     node *tail = NULL;  
  5.     int i = 0;  
  6.     if(num <= 0 || head == NULL)  
  7.     {  
  8.         return false;  
  9.     }  
  10.     for(i = 1; i < num; ++i)  
  11.     {  
  12.         if(cur == NULL)  
  13.         {  
  14.             return false;  
  15.         }  
  16.         cur = cur->next;  
  17.     }  
  18.     tail = cur;  
  19.     while(tail->next)  
  20.     {  
  21.         tail = tail->next;  
  22.     }  
  23.     tail->next = cur;  
  24.     return true;  
  25. }  

 

//给单链表建环,让尾指针,指向第num个节点,若没有,返回false bool bulid_looplink(node *head, int num) { node *cur = head; node *tail = NULL; int i = 0; if(num <= 0 || head == NULL) { return false; } for(i = 1; i < num; ++i) { if(cur == NULL) { return false; } cur = cur->next; } tail = cur; while(tail->next) { tail = tail->next; } tail->next = cur; return true; }

 

 

 

 

 

题目.检测单链表是否有环

 

//检测单链表是否有环,快慢指针   
  1. bool detect_looplink(node *head)  
  2. {  
  3.     node *quick_node = head->next, *slow_node = head;  
  4.     if(head == NULL || head->next == NULL)  
  5.     {  
  6.         return false;  
  7.     }  
  8.     while(quick_node != slow_node)  
  9.     {  
  10.         if(quick_node == NULL || slow_node == NULL)  
  11.             break;  
  12.         quick_node = quick_node->next->next;  
  13.         slow_node = slow_node->next;  
  14.     }  
  15.     if(quick_node != NULL && slow_node != NULL)    //非尾节点相遇   
  16.         return true;  
  17.     return false;  
  18. }  

 

//检测单链表是否有环,快慢指针 bool detect_looplink(node *head) { node *quick_node = head->next, *slow_node = head; if(head == NULL || head->next == NULL) { return false; } while(quick_node != slow_node) { if(quick_node == NULL || slow_node == NULL) break; quick_node = quick_node->next->next; slow_node = slow_node->next; } if(quick_node != NULL && slow_node != NULL) //非尾节点相遇 return true; return false; }

 

 

 

 题目.给单链表解环

 

ps:为了增加节点位图的效率,本应使用hash或则红黑树,这里不造车了,直接用 set容器

 

//找到有环节点,并解环,找到并解环,返回true,无环,返回false   
  1. //思路:先找到环节点:被2个节点指向的节点(一定有环的条件)ps:不考虑中间环,因为只有一个next节点,只可能是尾环   
  2. bool unloop_link(node *head)  
  3. {  
  4.     set node_bitmap;        //node的地址位图   
  5.     unsigned int num = 0;  
  6.     node *cur = head, *pre = NULL;  
  7.     while(cur != NULL)  
  8.     {  
  9.         if(!node_bitmap.count(cur) )              //该节点未被遍历过   
  10.         {  
  11.             node_bitmap.insert(cur);  
  12.             ++num;  
  13.         }  
  14.         else                               //指向已被遍历过的节点,此时pre节点为尾节点   
  15.         {  
  16.             pre->next = NULL;  
  17.             return true;  
  18.         }  
  19.         pre = cur;  
  20.         cur = cur->next;  
  21.     }  
  22.     return false;  
  23. }  

 

//找到有环节点,并解环,找到并解环,返回true,无环,返回false //思路:先找到环节点:被2个节点指向的节点(一定有环的条件)ps:不考虑中间环,因为只有一个next节点,只可能是尾环 bool unloop_link(node *head) { set node_bitmap; //node的地址位图 unsigned int num = 0; node *cur = head, *pre = NULL; while(cur != NULL) { if(!node_bitmap.count(cur) ) //该节点未被遍历过 { node_bitmap.insert(cur); ++num; } else //指向已被遍历过的节点,此时pre节点为尾节点 { pre->next = NULL; return true; } pre = cur; cur = cur->next; } return false; }

 

 

 

 

 

题目.检测两条链表是否相交

 

//检测两条链表是否相交,是则返回第一个交点,否则返回NULL   
  1. //思路:把2个链表各遍历一遍,记下长度length1和length2,若2者的尾节点指针相等,则相交。   
  2. //       之后再把长的链表从abs(len1-len2)的位置开始遍历,第一个相等的指针为目标节点   
  3. node* detect_intersect_links(node *first_link, node *second_link)  
  4. {  
  5.     int legnth1 = 1, length2 = 1, pos = 0;  
  6.     node *cur = NULL, *longer_link = first_link, *shorter_link = second_link;  
  7.     if(first_link == NULL || second_link == NULL)  
  8.     {  
  9.         return NULL;  
  10.     }  
  11.     while(first_link->next || second_link->next)     //遍历2个链表   
  12.     {  
  13.         if(first_link->next)  
  14.         {  
  15.             first_link = first_link->next;  
  16.             ++legnth1;  
  17.         }  
  18.         if(second_link->next)  
  19.         {  
  20.             second_link = second_link->next;  
  21.             ++length2;  
  22.         }  
  23.     }  
  24.     if(first_link != second_link)                 //比较尾节点   
  25.     {  
  26.         return NULL;  
  27.     }  
  28.     pos = legnth1 - length2;  
  29.     if(legnth1 < length2)                  //保证 longer_link为长链表   
  30.     {  
  31.         pos = length2 - legnth1;  
  32.         cur = longer_link;  
  33.         longer_link = shorter_link;  
  34.         shorter_link = cur;  
  35.     }  
  36.     while(pos-- > 0)  
  37.         longer_link = longer_link->next;  
  38.     while(longer_link || shorter_link)  
  39.     {  
  40.         if(longer_link == shorter_link)                  //找到第一个交点   
  41.         {  
  42.             return longer_link;  
  43.         }  
  44.         longer_link = longer_link->next;  
  45.         shorter_link = shorter_link->next;  
  46.     }  
  47.     return NULL;  
  48. }  

 

//检测两条链表是否相交,是则返回第一个交点,否则返回NULL //思路:把2个链表各遍历一遍,记下长度length1和length2,若2者的尾节点指针相等,则相交。 // 之后再把长的链表从abs(len1-len2)的位置开始遍历,第一个相等的指针为目标节点 node* detect_intersect_links(node *first_link, node *second_link) { int legnth1 = 1, length2 = 1, pos = 0; node *cur = NULL, *longer_link = first_link, *shorter_link = second_link; if(first_link == NULL || second_link == NULL) { return NULL; } while(first_link->next || second_link->next) //遍历2个链表 { if(first_link->next) { first_link = first_link->next; ++legnth1; } if(second_link->next) { second_link = second_link->next; ++length2; } } if(first_link != second_link) //比较尾节点 { return NULL; } pos = legnth1 - length2; if(legnth1 < length2) //保证 longer_link为长链表 { pos = length2 - legnth1; cur = longer_link; longer_link = shorter_link; shorter_link = cur; } while(pos-- > 0) longer_link = longer_link->next; while(longer_link || shorter_link) { if(longer_link == shorter_link) //找到第一个交点 { return longer_link; } longer_link = longer_link->next; shorter_link = shorter_link->next; } return NULL; }

 

 

 

题目.不输入头节点,删除单链表的指定节点(只给定待删除节点指针)

 

//无头节点,随机给出单链表中一个非头节点,删除该节点,当传入空节点,或者尾节点时,返回false   
  1. //思路:由于没有头节点,非循环单链表,无法获取目标节点的前节点,所以只能把它的next节点数据前移,并删除next节点   

 

  • //ps:当传入节点为尾节点,无法用此方法删除   
  • bool withouthead_delete_node(node *target_node)  
  • {  
  •     node *cur = NULL;  
  •     if(target_node == NULL || target_node->next == NULL)   //空节点或者尾节点,失败   
  •     {  
  •         return false;  
  •     }  
  •     cur = target_node->next;  
  •     target_node->name = cur->name;  
  •     target_node->next = cur->next;  
  •     delete cur;  
  •     return true;  
  • }  

 

 

题目: 1.判断2个链表是否相交    2.判断一个链表内部是否有循环

 

第一步:

用3个指针应该可以判断相交,P1、P3指向链表A,P1每次+1 P3每次+2,如果P3跑到尾了,则P1 = P3,让P1在尾巴等着(情况1)
如果P1与P3相遇了,则说明有环路,P1停下在相遇点等着(情况2)

P2和P3指向链表B,P2每次+1 P3每次+2,如果P3跑到尾了,如果第一步属于情况1,则判断是否P3 = P1,如果相等,说明A与B相交
如果第一步属于情况2,则A与B不相交。

如果P2和P3相遇了,则说明B中也有环路。让P2在相遇点停下,P1开始跑,每步+1,P3开始跑,每步+2,

如果P3与P2再次相遇前没有与P1相遇,且P1与P2也未相遇,则A与B不相交,否则相交。

 

 

说的有点乱,整理一下,用3个指针应该可以判断相交

第一步:

P1、P3指向链表A,P1每次+1 P3每次+2

情况1-1:如果P3跑到尾了,则P1 = P3,让P1在尾巴等着。
情况1-2:如果P1与P3相遇了,则说明有环路,P1停下在相遇点等着。

第二步:

P2和P3指向链表B,P2每次+1 P3每次+2

情况2-1:如果P3跑到尾了。
    如果情况1-1,则判断是否P3 = P1,如果相等,说明A与B相交,否则不相交。
    如果情况1-2,则A与B不相交。  

情况2-2:如果P2和P3相遇了,则说明B中也有环路。让P2在相遇点停下。
    如果情况1-1,则A与B不相交。  
    如果情况1-2,P1开始跑,每步+1,P3继续跑,每步+2,  
    如果P3与P2再次相遇前没有与P1相遇,且P1与P2也未相遇,则A与B不相交,否则相交。

转载于:https://www.cnblogs.com/lucyjiayou/archive/2012/09/18/2692365.html

你可能感兴趣的:(链表题目总结)