数据结构之链表基本操作总结

数组与链表的区别
 数组(顺序存储)和链表(链式存储)是两种不同的数据存储方式。

数组是一组具有相同类型和名称的变量的集合,这些变量称为数组的元素,每个数组元素都有一个编号,这个编号称为数组的下标,可以通过下标来区别并访问这些元素,数组元素的个数称为数组的长度。

链表的特性是在中间任意位置添加、删除元素都非常快,不需要移动其他元素。对于单链表,链表中每一个元素都要保存一个指向下一个元素的指针;对于双链表,每个元素既要保存一个指向下一个元素的指针,还要保存一个指向上一个元素的指针;循环链表(单向、双项)则在最后一个元素中保存一个指向第一个元素的指针。

区别:

1、逻辑结构:数组必须事先定义固定的长度,不能适应数据动态地增减的情况,即在数组使用前,就必须对数组的大小进行固定;当数据增加时,可能超过原先定义的元素个数;当数据减少时,造成内存浪费。数组中插入、删除数据项时,需要移动其他数据项。而链表采用动态内存形式实现,可以适应数据动态地增减情况,需要时可以用new/malloc分配内存空间,不需要时用delete/free将已分配的空间释放,不会造成内存空间浪费,且可以方便的插入、删除数据项。

2、内存结构:(静态)数组从栈中分配内存空间,方便快捷,但是自由度小;链表从堆中分配内存,自由度大,但是申请管理比较麻烦;

3、数组中数据在物理内存中是顺序存储的,而链表是随机存储的。数组的随机访问效率很高,可以直接定位,但插入、删除操作的效率比较低。链表在插入、删除操作上相对数组有很高的效率,而如果要访问链表中的某个元素,那就得从表头逐个遍历,直到找到所需要的元素为止,所以链表的随机访问效率比数组低。

4、链表不存在越界问题(存储溢出),数组有越界问题。数组便于查询,链表便于插入、删除,数组节省空间但长度固定,链表虽然变长但占据更多存储空间。


数组存储效率高、存储速度快,如果需要频繁访问数据,很少插入删除操作,则用数组;反之,如果频繁插入删除,则应使用链表。
 
单链表
 
  //
struct  ListNode
{
     int  val ;
     ListNode  * next ;
     ListNode ( int  x ) : val ( x ) , next ( nullptr ) { }
} ;
/*
1.
2.
1head
2nextNULL
3
3.使p
*p.data //(*p).data
p->data //
p->next //
*/
  解决链表问题时,一定要画图!!!!只有画好图了,指针之间的相互关系才能够比较清晰地呈现出来,这样写的时候正确率就高多了。

链表之如何使用链表头
  节点:数据域和指针域的和;数据域存储数据元素的信息,指针域指示直接后继存储位置。

头结点:单链表的开始节点之附设一个类型相同的节点,称之为头结点; 
               头结点的数据域可以不存储任何信息,也可以存放如线性表的长度等附加信息;
                头节点的指针域存储指向开始结点的指针,即第一个元素结点的存储位置;

头结点的作用:
         1、对带头结点的链表,在表的任何结点之前插入结点或删除表中任何结点,所要做的都是修改前一结点的指针域,因为任何元素结点都有前驱结点。若链表无头结点,则首元素结点无前驱结点,在其前插入结点或删除该结点时操作会复杂些;
         2、对带头结点的链表,表头指针是指向首节点的非空指针,因此空表和非空表的处理是一样的;


开始结点:链表中第一个结点,无直接前驱借结点;

链表头指针;指向链表开始结点的指针(无头结点时),单链表由头指针唯一确定,所以单链表可以用头指                       针的名字来命名;头指针的设置是的对链表第一个位置上的操作与在表其他位置上的操作一                          致

头结点;人为的在链表的开始结点之前附加的一个结点。有了头结点,头指针指向头结点,无论链表是否为                空,头指针总是非空。


通常要对链表的开始节点进行操作时,最好添加个头结点。

单链表之建立、测长、打印、删除、插入
  note head

 
 
#include <iostream>
using  namespace  std ;
struct  ListNode
{
     int  val ;
     ListNode  * next ;
     ListNode ( int  x ) : val ( x ) , next ( nullptr ) { }
} ;
/***************************************************************************************************/
//
ListNode  * creat ( )
{
     ListNode  * head = new  ListNode ( 0 ) ;
     ListNode  * p = head ;
     ListNode  * node = nullptr ;
     int  x = 0 ;
     int  cycle = 1 ;
     while ( cycle )
     {
         cout << "please input the data:" << endl ;
         cin >> x ;
         if ( x != 0 )        //0
         {
              node = new  ListNode ( x ) ;
              p -> next = node ;
              p = node ;
         }
         else
              cycle = 0 ;
     }
     p -> next = nullptr ;   //
     //head=head->next;
     return  head ;
}
/***************************************************************************************************/
//
void  printList ( ListNode  * head )   //notehead
{
     if ( head -> next == nullptr )
     {
         cout << "list is empty!" << endl ;
         return  ;
     }
     ListNode  * p = head -> next ;
     int  index = 0 ;
     while ( p != nullptr )
     {
         cout << "" <<++ index << "" << p -> val << endl ;
         p = p -> next ;
     }
}
/****************************************************************************************************/
//
int  getListLength ( ListNode  * head )   //notehead
{
     int  len = 0 ;
     ListNode  * p = head -> next ;
     while ( p != nullptr )
     {
         ++ len ;
         p = p -> next ;
        
     }
     return  len ;
}
/****************************************************************************************************/
//
//dataii=pos
//i-1O(n)
//;ii0
ListNode  * insertList ( ListNode  * head , int  pos , int  data ) //notehead
{
      ListNode  * newNode = new  ListNode ( data ) ;
     
      ListNode  * p = head ;
      int  index = 1 ;
      while ( p != nullptr && index < pos )
      {
          p = p -> next ;
          ++ index ;
      }
      newNode -> next = p -> next ;
      p -> next = newNode ;
      return  head ;
}
/**************************************************************************************************/
//:i
//
//ni1=<i<=n,i=n+1
//
//ppindex<i
//On
ListNode  * deleteNode ( ListNode  * head , int  pos ) //pos11
    
{
         ListNode  * p = head ;
         if ( p -> next == nullptr )   //
         {
               cout << "" << endl ;
              return  nullptr ;
         }
         ListNode  * node = nullptr ;
         int  index = 1 ;
         while ( p != nullptr && index < pos )
         {
              p = p -> next ;
              ++ index ;
         }
         if ( p != nullptr && p -> next != nullptr )  
         {
         node = p -> next ;
         p -> next = node -> next ;
         delete  node ;
         }
         return  head ;
}
/***************************************************************************************************/
int  main ( )
{
     ListNode  * head = new  ListNode ( 0 ) ;
     head = creat ( ) ;
     cout << "" << endl ;
     printList ( head ) ;
     int  len = getListLength ( head ) ;
     cout << "" << len << endl ;
    
     int  pos = 1 ;
     int  data = 50 ;
     insertList ( head , pos , data ) ;
     cout << "" << endl ;
     printList ( head ) ;
    
    
     int  i = 5 ;
     deleteNode ( head ,  i ) ;
     cout << "" << endl ;
     printList ( head ) ;
    
     system ( "pause" ) ;
     return  0 ;
}
单链表之删除单链表的头元素
 要删除头元素,首先需要通过头结点定位头元素,并将头结点指向头元素的下一个元素,然后释放头元素的空间;

 
ListNode  *  deleteHead ( ListNode  * head ) //head
{
     ListNode  * beginNode = new  ListNode ( 0 ) ;
     beginNode -> next = head ;
     ListNode  * node = head ;
     beginNode -> next = head -> next ;
     delete  node ;
     ListNode  * result = beginNode -> next ;
     delete  beginNode ;
     return  result ;             //  
}
  void  deleteHead ( ListNode  * head ) // head
  {
      ListNode  * node = head -> next ;
      head -> next = node -> next ;
      delete  node ;
  }
单链表之查找第i节点、中间节点、倒数第k个节点
  i

ListNode  * searchNode ( ListNode  * head , int  pos ) //head
{
     if ( head -> next == nullptr || pos < 0 )
         return  nullptr ;
     if ( pos == 0 )
         return  head ;
     ListNode  * p = head -> next ;
     while ( -- pos )
     {
         p = p -> next ;
         if ( p == nullptr )
         {
              cout << "incorrect postion to search node!" << endl ;
              break ;
         }
     }
     return  p ;
}
 /**************************************************************************************************/
查找单链表的中间节点
//方法一:先求链表的长度len,然后遍历len/2的距离即可查找到单链表的中间节点,需要遍历链表两次
//方法二:采用双指针,从链表头开始遍历,一个指针slow一次走一步,一个指针fast一次走两步,当fast
//        到达链表尾部时,slow恰好到达链表中间(fast到达链表尾部,当链表长度为奇数时,此时slow
//        指向的即为中间节点;当链表长度为偶数时,此时slow及slow的下一个元素均为中间节点)
//        只需遍历链表一次 
 
//
ListNode  * searchMidNode ( ListNode  * head )
{
     if ( head -> next == nullptr )
         return  head ;
     ListNode  * slow = head -> next ;
     ListNode  * fast = head -> next ;
     while ( fast != nullptr && fast -> next != nullptr && fast -> next -> next != nullptr ) //lenslowslowmid
                                     //while(fast!=nullptr&&fast->next!=nullptr)lenslowslow mid                                                          

       {
         slow = slow -> next ;
         fast = fast -> next -> next ;
     }

 
     return  slow ;
}
 
  查找单链表中倒数第k个元素
//方法一:需遍历两次链表;先求链表的长度len,然后遍历len-k的距离即可查找到单链表的倒数第k个节点
//方法二:遍历一次链表,时间复杂度为O(n);设置两个指针p1、p2,让p2先走k-1步,然后p1、p2再同时走,
//        当p2走到链表尾时,p1所指位置就是所要找的节点
/***************************************************************************************************/
//
ListNode  * searchReverseKthNode ( ListNode  * head , int  k )
{
     if ( head -> next == nullptr || k == 0 )
        return  head ;
    
     ListNode  * p1 = head -> next ;
     ListNode  * p2 = head -> next ;
     while ( p2 != nullptr &&-- k )
     {
         p2 = p2 -> next ;
     }
     while ( p2 -> next != nullptr )
     {
         p1 = p1 -> next ;
         p2 = p2 -> next ;
     }
     return  p1 ;  
}
单链表之实现单链表反转、从尾到头打印单链表(同剑指offerT5)

  转:
 
                   

 
/***************************************************************************************************/

//
ListNode  * reverse ( ListNode  * head )
{
     if ( head -> next == nullptr && head -> next -> next == nullptr )
         return  head ;
     ListNode  * tail = head -> next ;
     ListNode  * cur = tail -> next ;
     while ( cur != nullptr )
     {
         //
         tail -> next = cur -> next ;
         //
         cur -> next = head -> next ;
         head -> next = cur ;
         //
         cur = tail -> next ;
     }
     return  head ;
}
//
//         
ListNode  * reverse2 ( ListNode  * head )
{
     if ( head -> next == nullptr )
         return  head ;
     ListNode  * pre = head -> next ;
     ListNode  * cur = pre -> next ;
     pre -> next = nullptr ;  //
     ListNode  * tmp = nullptr ;
     while ( cur != nullptr )
     {
         tmp = cur -> next ;
         cur -> next = pre ;
         pre = cur ;
         cur = tmp ;
     }
     head -> next = pre ; //  
     return  head ;
}
 

逆序输出单链表元素:(同剑指offerT5)
//方法一:从头到尾遍历节点,每经过一个节点的时候,把该节点放到一个栈中,当遍历完整个链表后,再从栈顶
//        输出节点的值;只需遍历一遍链表,但需维护一个额外的栈空间;

//方法二:在递归函数之后输出的当前元素,这样能确保输出第n个节点的元素语句永远在第n+1个递归函数之后执行, 也就是说第n个元素永远在第n+1个元素之后输出,最终先输出最后一个元素;  

注意:
递归本质上就是一个栈结构;  基于递归的代码看起来很简单,单链表非常长时,就会导致函数调用的层级很深 ,从而可能导致函数调用栈溢出。显式用栈基于循环的代码鲁棒性要好一些。

 
include < iostream >
#include <stack>
using  namespace  std ;
struct  ListNode 
{
     int  val ;
     ListNode  * next ;
     ListNode ( int  x ) : val ( x ) , next ( nullptr ) { }
} ;
//
ListNode  * creat ( )
{
     ListNode  * head = new  ListNode ( -1 ) ;
     ListNode  * p = head ;
     ListNode  * node = nullptr ;
     int  x = 0 ;
     int  cycle = 1 ;
     while ( cycle )
     {
         cout << "please input the data:" << endl ;
         cin >> x ;
         if ( x != 0 )        //0
         {
              node = new  ListNode ( x ) ;
              p -> next = node ;
              p = node ;
         }
         else
              cycle = 0 ;
     }
     p -> next = nullptr ;   //
     //head=head->next;
     return  head ;
}
//
void  printList ( ListNode  * head )   //notehead
{
     if ( head -> next == nullptr )
     {
         cout << "list is empty!" << endl ;
         return  ;
     }
     ListNode  * p = head -> next ;
     int  index = 0 ;
     while ( p != nullptr )
     {
         cout << "" <<++ index << "" << p -> val << endl ;
         p = p -> next ;
     }
}
// 
void  printReversely1 ( ListNode  * head )
{
     stack < ListNode  *> stackNode ;
     ListNode  * p = head -> next ;
     while ( p != nullptr )
     {
         stackNode . push ( p ) ;
         p = p -> next ;
     }
     int  index = 1 ;
     while ( ! stackNode . empty ( ))
     {
         p = stackNode . top ( ) ;
         cout << "" << index << "" << p -> val << endl ;
         stackNode . pop ( ) ;
     }
}
  //
void  printListReversely2 ( ListNode  * head )
{
     if ( head -> next != nullptr )
     {
         printListReversely2 ( head -> next ) ;
         int  index = 1 ;
         cout << "" << index ++<< "" ;
         cout << head -> next -> val << endl ;
     }
}
int  main ( )
{
      ListNode  * head = new  ListNode ( 0 ) ;
     head = creat ( ) ;
     cout << "" << endl ;
     printList ( head ) ;
     cout << endl ;
     cout << "1" << endl ;
     printReversely1 ( head ) ;
     cout << "" << endl ;
     printList ( head ) ;
     cout << endl ;
     cout << "2" << endl ;
     printListReversely2 ( head ) ;
     cout << "" << endl ;
     printList ( head ) ;
     cout << endl ;
     system ( "pause" ) ;
     return  0 ;
}
 
 
 
//
void  printListReversely ( ListNode  * head )
{
     if ( head -> next != nullptr )
     {
         printListReversely ( head -> next ) ;
         cout << head -> next -> val << endl ;
     }
}
 

题目变形
1、从尾到头输出一个字符串;
2、定义一个函数求字符串长度,要求该函数体中不能声明任何一个变量; 
要求不使用额外变量,实现strlen函数:
 
 
//
//
#include  <cstdlib>  
#include  <iostream>  
using  namespace  std ;  
int  getLen ( char  * str )  
{     
     if ( * str ==  '/0' )  
         return  0 ;  
          
     return  getLen ( str  +  1 )  +  1 ;  
}  
int  main ( int  argc ,  char  * argv [ ])  
{  
     char  str [ ]  =  { "abcdefghigkl" } ;  
      
     cout  <<  getLen ( str )  <<  endl ;  
      
     system ( "PAUSE" ) ;  
     return  EXIT_SUCCESS ;  
}
//
int  strlen ( const  char  * str )
{
    return  * str ? ( strlen ( str +1 ) +1 ) : 0 ;
}
 
 
//
//
#include  <cstdlib>  
#include  <iostream>  
using  namespace  std ;  
int  getLen ( char  * str )  
{     
     if ( * str ==  '/0' )  
         return  0 ;  
          
     return  getLen ( str  +  1 )  +  1 ;  
}  
int  main ( int  argc ,  char  * argv [ ])  
{  
     char  str [ ]  =  { "abcdefghigkl" } ;  
      
     cout  <<  getLen ( str )  <<  endl ;  
      
     system ( "PAUSE" ) ;  
     return  EXIT_SUCCESS ;  
}
//
int  strlen ( const  char  * str )
{
    return  * str ? ( strlen ( str +1 ) +1 ) : 0 ;
}
 
 
strlen
size_t  strlen ( const  char  * str )
//strlenNULLcore
{
     const  char  * eos = str ;
     while ( *( eos ++) ) ;
     return  ( eos - str -1 ) ;
}
单链表之判断单链表是否存在环、求环的长度、求环的首节点(同leetcode(141、142))
单链表有环是指单链表中某个节点的next指针域指向的是链表中在它之前的某个节点,这样在链表的尾部形成一个环形结构。



给定一个链表,判断它是否包含一个环。
【注意】
 
1. 空链表不成环

   2. 一个节点自环

   3. 一条链表完整成环
linked-list-cycle
 

【方法一】 空间复杂度 O(n),时间复杂度 O(N )

用一个哈希表 unordered_map<ListNode *, bool> visited,记录每个元素是否被访问过,一旦出现某个元素被重复访问,说明存在环。

 

 
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class  Solution  {
public :
     bool  hasCycle ( ListNode  * head )
  {
      if ( head == nullptr )
          return  false ;
      unordered_map < ListNode * , bool >  visited(false) ;
      bool  isCycle = false ;
    
      while ( head != nullptr )
      {
    
          if ( visited [ head ] == true )
          {
               isCycle = true ;
               break ;
          }
          else
               visited [ head ] = true ;
          head = head -> next ;
      }
      return  isCycle ;
  }
} ;
  【方法二】 时间复杂度 O(n),空间复杂度 O(1) 的。

使用两个指针slow,fast。两个指针都从表头开始走,slow每次走一步,fast每次走两步,如果fast遇到null,则说明没有环,返回false;如果slow==fast,说明有环,并且此时fast超了slow一圈,返回true。

为什么有环的情况下二者一定会相遇呢?因为fast先进入环,在slow进入之后,如果把slow看作在前面,fast在后面每次循环都向slow靠近1,所以一定会相遇,而不会出现fast直接跳过slow的情况。


这里需要注意的一点是算法中循环的条件,这是一个很容易被忽略的细节。

1)因为fast指针比slow指针走得快,所以只要判断fast指针是否为空就好。由于fast指针一次走两步,fast.next可能已经为空(当fast为尾结点时),fast.next.next将会导致NullPointerException异常,所以在while循环中我们要判断fast.next是否为空;

2)考虑一个特殊情况,当输入的链表为空时,算法应该返回false,空链表肯定是不含有环的。如果没有fast != null,也会导致fast.next抛出NullPointerException异常。    

 

 
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class  Solution  {
public :
     bool  hasCycle ( ListNode  * head )
  {
      if ( head == nullptr )
          return  false ;
      ListNode  * slow = head ;
      ListNode  * fast = head ;
      while ( fast != nullptr && fast -> next != nullptr )
      {
          slow = slow -> next ;
          fast = fast -> next -> next ;
          if ( slow == fast )
               return  true ;
      }
      return  false ;
  }
} ;
 


题意: 

如何找到环的第一个节点?

分析:
 
 1)先判断是否存在环

使用两个指针slow,fast。两个指针都从表头开始走,slow每次走一步,fast每次走两步,如果fast遇到null,则说明没有环,返回false;如果slow==fast,说明有环,并且此时fast超了slow一圈,返回true。

为什么有环的情况下二者一定会相遇呢?因为fast先进入环,在slow进入之后,如果把slow看作在前面,fast在后面每次循环都向slow靠近1,所以一定会相遇,而不会出现fast直接跳过slow的情况。 

2)找环的第一个节点


设:链表头是X,环的第一个节点是Y,slow和fast第一次的交点是Z。各段的长度分别是a,b,c,如图所示。环的长度是L。slow和fast的速度分别是qs,qf。

第一次相遇时slow走过的距离:a+b,fast走过的距离:a+b+c+b。

因为fast的速度是slow的两倍,所以fast走的距离是slow的两倍,有 2(a+b) = a+b+c+b,可以得到a=c(这个结论很重要!)

发现L=b+c=a+b,也就是说,从一开始到二者第一次相遇,循环的次数就等于环的长度。

已经得到了结论a=c,那么让两个指针分别从X和Z开始走,每次走一步,那么正好会在Y相遇!也就是环的第一个节点。

 
struct  ListNode
{
     int  val ;
     ListNode  * next ;
     ListNode ( int  x ) : val ( x ) , next ( nullptr ) { }
} ;
class  Solution
{
public :
     ListNode  * detectCycle ( ListNode  * head )
     {
         if ( head == nullptr )
              return  nullptr ;
         ListNode  * slow = head ;
         ListNode  * fast = head ;
         ListNode  * slow2 = head ;
         while ( fast != nullptr && fast -> next != nullptr )
         {
              slow = slow -> next ;
              fast = fast -> next -> next ;
              if ( fast == slow )
              {
                   while ( slow != slow2 )
                   {
                        slow = slow -> next ;
                        slow2 = slow2 -> next ;
                   }
                   return  slow2 ;
              }
         }
         return  nullptr ;
     }
} ;
 


【题目拓展】 
 

      
1. 环的长度是多少?
       
方法一

第一次相遇后,让fast停着不走了,slow继续走,记录到下次相遇时循环了几次。

方法二

第一次相遇时slow走过的距离:a+b,fast走过的距离:a+b+c+b。

因为fast的速度是slow的两倍,所以fast走的距离是slow的两倍,有 2(a+b) = a+b+c+b,可以得到a=c(这个结论很重要!)

我们发现L=b+c=a+b,也就是说,从一开始到二者第一次相遇,循环的次数就等于环的长度。

 
 

2. 如何找到环中第一个节点(即Linked List Cycle II)?
        我们已经得到了结论a=c,那么让两个指针分别从X和Z开始走,每次走一步,那么正好会在Y相遇!也就是环的第一个节点。 




      3. 如何将有环的链表变成单链表(解除环)?
         在上一个问题的最后,将c段中Y点之前的那个节点与Y的链接切断即可。 



      4. 如何判断两个单链表是否有交点?如何找到第一个相交的节点?
         先判断两个链表是否有环,如果一个有环一个没环,肯定不相交;如果两个都没有环,判断两个列表的尾部是否相等;如果两个都          有环,判断一个链表上的Z点是否在另一个链表上。
      5、(接问题4)
如何找到第一个相交的节点?
        求出两个链表的长度L1,L2(如果有环,则将Y点当做尾节点来算),假设L1<L2,用两个指针分别从两个链表的头部开始走,长度         为L2的链表先走(L2-L1)步,然后两个一起走,直到二者相遇。



单链表之合并两个有序单链表
 题目:已知两个有序单链表head1、head2(假设链表元素为升序排列),把他们合并成一个链表,合并后依然有序;使用后递归和非递归方式实现;
 

//方法一: 递归;
              设两个链表的头结点分别为head1和head2,如果head1为空,则直接返回head2,;如果head2为空
//              则直接返回head1;如果head1链表的第一个数据小于head2链表的第一个数据,则把head1链表的
//              元素存储到新合并的链表中,递归遍历去掉第一个元素的head1链表和整个head2链表。如果head1
//              链表的第一个元素>=head2链表的第一个元素,则把head2链表的第一个元素存储到新合并的链表
//               中,递归遍历整个head1链表和去除第一个元素后的head2链表。直到两个链表的节点都被加入到
//               新合并的链表中。
//               递归终止条件:若head1为空,返回head2指针(head);若head2为空,返回head1指针(head);
//        递归方法所使用的栈空间与链表的长度成正比。  
//
ListNode  * mergeRecursive ( ListNode  * head1 , ListNode  * head2 ) //head1head2
{
    
     if ( head1 == nullptr )
         return  head2 ;
     if ( head2 == nullptr )
         return  head1 ;
     ListNode  * newHead = nullptr ;
     if ( head1 -> val < head2 -> val )
     {
    
         newHead = head1 ;
         newHead -> next = mergeRecursive ( head1 -> next , head2 ) ;
     }
     else
     {
         newHead = head2 ;
         newHead -> next = mergeRecursive ( head1 , head2 -> next ) ;
     }
     return  newHead ;
}
 

方法二 :非递归;
                    分别用两个指针head1和head2遍历两个链表,如果当前head1指向的数据小于head2指向的数据
                   则将head1指向的节点归并入合并后的链表中;否则将head2指向的节点归并入合并后的链表中,
                  如果有一个链表遍历结束,则把未结束的链表连接到合并后的链表尾部;

 
//
ListNode  * mergeList ( ListNode  * head1 , ListNode  * head2 ) //head1head2
{
     ListNode  * newHead = new  ListNode ( 0 ) ;
     ListNode  * node = newHead ;
     while ( head1 != nullptr && head2 != nullptr )
     {
         if ( head1 -> val < head2 -> val )
         {
              node -> next = head1 ;
              node = head1 ;
              head1 = head1 -> next ;
         }
         else
         {
              node -> next = head2 ;
              node = head2 ;
              head2 = head2 -> next ;
         }
     }
     if ( head1 != nullptr )
     {
         node -> next = head1 ;
     }
     if ( head2 != nullptr )
     {
         node -> next = head2 ;
     }
     return  newHead ;  //
}
 

单链表之删除链表的重复元素
 题目:一个无序链表 如list={1,8,10,2,3,4,4,2,5,6,3,12,4,7},要求去掉重复项,并保留原顺序,去重后list={1,8,10,2,3,4,5,6,12,7}。


方法一:使用hash表,时间复杂度O(n),空间复杂度O(n)
   1、建立一个hash表,key为链表中已遍历的节点内容,开始时为空;
  2、从头开始遍历链表中的节点   
         1)如果节点内容已经在hash中了,则删除此节点,继续向后遍历;
         2)如果节点内容不在hash中,则保留此节点,将节点内容添加到hash中,继续遍历
 
//
ListNode  *  deleteDuplicateFromUnsortedList ( ListNode  * head )
{
     if ( head -> next == nullptr && head -> next -> next == nullptr )
         return  head ;
      unordered_map < int , bool >  visited ( false ) ;
      ListNode  * pre = head ;
      ListNode  * cur = pre -> next ;
      ListNode  * tmp = nullptr ;
      while ( cur != nullptr )
      {
    
          if ( visited [ cur -> val ])
          {
              tmp = cur ;   //tmp
              pre -> next = cur -> next ;  //
              cur = cur -> next ;
              delete  tmp ;  //
          }
          else
          {
               visited [ cur -> val ] = true ;
               pre = pre -> next ;
               cur = cur -> next ;
          }
        
      }
      return  head ;
}
方法二不使用额外空间,直接在原链表上进行操作,时间复杂度O(n^2)。
//       1、建立指针cur用于遍历链表;
//       2、建立指针p,p遍历cur之后的节点,并与cur的内容进行比较;
//       3、建立指针tmp,tmp保存要删除的节点,把需要删除的节点前后相连,删除重复节点 
 
 
//
ListNode  *  deleteDuplicateFromUnsortedList2 ( ListNode  * head )
{
       if ( head -> next == nullptr )
           return  head ;
       ListNode  * cur = head -> next ;
       ListNode  * p = nullptr ;
       ListNode  * tmp = nullptr ;
       while ( cur != nullptr )
       {
           p = cur ;
           while ( p -> next != nullptr )
           {
                if ( p -> next -> val == cur -> val )
                {
                     tmp = p -> next ;
                     p -> next = p -> next -> next ;
                     delete  tmp ;
                       
                }
                else
                {
                     p = p -> next ;
                 }
            }
           cur = cur -> next ;
       }
       return  head ;
}
//
ListNode  *  deleteDuplicateFromUnsortedList3 ( ListNode  * head )
{
     if ( head -> next == nullptr )
         return  head ;
     ListNode  * tmp = head ;    //headtmphead
     head -> next = deleteDuplicateFromUnsortedList3 ( head -> next ) ; //head->nexthead
                                                                          //
     ListNode  * cur = head -> next ; //curheadtmp=head
       while ( cur != nullptr )
       {
           if ( cur -> val == head -> val ) //headheadhead
                                          //
           {
                tmp -> next = cur -> next ;
                delete  cur ;
                cur = tmp -> next ;
           }
           else
           {
                cur = cur -> next ;
                tmp = tmp -> next ; //tempheadcurcur
                                  //tmpheadcurtemp->nextcur
           }
       }
       return  head ;
}

单链表之判断两个单链表有无公共节点(即是否交叉)
 注意:单链表相交是指两个链表存在完全重合的部分(不是交叉到一个点)。
           附:求两个链表的第一个公共节点

注意:输入的两个链表有三种情况:
1、一个链表有环,另一个链表无环,则两个链表不可能相交;
2、两个链表均有环;
3、两个链表均无环;

【分析】




 
 
  //
//       
struct  ListNode
{
     int  val ;
     ListNode  * next ;
     ListNode ( int  x ) : val ( x ) , next ( nullptr ) { }
} ;
class  Solution
{
private :
     //
     bool  hasCycle ( ListNode  * head )  //head
  {
      if ( head == nullptr )
           return  false ;
      ListNode  * slow = head ;
      ListNode  * fast = head ;
      while ( fast != nullptr && fast -> next != nullptr )
      {
           slow = slow -> next ;
           fast = fast -> next -> next ;
           if ( slow == fast )
                return  true ;
      }
      return  false ;
  }
private :
     //
     ListNode  * detectCycle ( ListNode  * head ) //head
     {
         if ( head == nullptr )
              return  nullptr ;
         ListNode  * slow = head ;
         ListNode  * fast = head ;
         ListNode  * slow2 = head ;
         while ( fast != nullptr && fast -> next != nullptr )
         {
              slow = slow -> next ;
              fast = fast -> next -> next ;
              if ( fast == slow )
              {
                   while ( slow != slow2 )
                   {
                        slow = slow -> next ;
                        slow2 = slow2 -> next ;
                   }
                   return  slow2 ;
              }
         }
         return  nullptr ;
     }
private :
//
int  getListLength ( ListNode  * head )   //notehead
{
     int  len = 0 ;
     ListNode  * p = head -> next ;
     while ( p != nullptr )
     {
         ++ len ;
         p = p -> next ;
        
     }
     return  len ;
}
public :
//
//
ListNode  *  findFristCommonNode1 ( ListNode  * head1 , ListNode  * head2 ) //notehead
{
     if ( head1 -> next == nullptr || head2 -> next == nullptr )
     {
         cout << "" << endl ;
              return  nullptr ;
     }
     ListNode  * p1 = head1 -> next ;
     ListNode  * p2 = head2 -> next ;
     while ( p1 != nullptr )
     {
         while ( p2 != nullptr )
         {
              if ( p1 == p2 )
              {
                   cout << "" << endl ;
                   return  p1 ;
              }
              else
                   p2 = p2 -> next ;
         }
         p1 = p1 -> next ;
     }
     cout << "" << endl ;
     return  nullptr ;
}
//
     ListNode  *  findFristCommonNode2 ( ListNode  * head1 , ListNode  * head2 ) //notehead
     {
         if ( head1 -> next == nullptr || head2 -> next == nullptr )
     {
         cout << "" << endl ;
              return  nullptr ;
     }
         int  len1 = getListLength ( head1 ) ;
         int  len2 = getListLength ( head2 ) ;
         int  k = len1 - len2 ;
         ListNode  * plong = nullptr ;
         ListNode  * pshort = nullptr ;
         if ( k > 0 )
         {
              plong = head1 -> next ;
              pshort = head2 -> next ;
              while ( k -- )
              {
                   plong = plong -> next ;
              }
         }
         else
         {
              plong = head2 -> next ;
              pshort = head1 -> next ;
              k = ( - k ) ;
              while ( k -- )
              {
                   plong = plong -> next ;
              }
         }
         while ( plong != nullptr && pshort != nullptr && plong != pshort )
         {
              plong = plong -> next ;
              pshort = pshort -> next ;
         }
         if ( plong == pshort )
         {
              cout << "" << endl ;
              return  plong ;
         }
         cout << "" << endl ;
         return  nullptr ;
     }
//
ListNode  *  findFristCommonNode3 ( ListNode  * head1 , ListNode  * head2 ) //notehead
{
     if ( head1 -> next == nullptr || head2 -> next == nullptr )
     {
         cout << "" << endl ;
              return  nullptr ;
     }
     ListNode  * p = head1 -> next ;
     ListNode  * newHead = p ;
     while ( p -> next != nullptr )
     {
         p = p -> next ;
     }
     p -> next = head2 -> next ;
     if ( hasCycle ( newHead ))
     {
          cout << ""  << endl ;
         return  detectCycle ( newHead ) ;
     }
     cout << "" << endl ;
     return  nullptr ;
}
//
ListNode  *  findFristCommonNode4 ( ListNode  * head1 , ListNode  * head2 ) //notehead
{
     if ( head1 -> next == nullptr || head2 -> next == nullptr )
     {
         cout << "" << endl ;
              return  nullptr ;
     }
     stack < ListNode  *> stack1 ;
     stack < ListNode  *> stack2 ;
     ListNode  * p1 = head1 -> next ;
     ListNode  * p2 = head2 -> next ;
     ListNode  * commonNode = nullptr ;
     while ( p1 != nullptr )
     {
         stack1 . push ( p1 ) ;
         p1 = p1 -> next ;
     }
     while ( p2 != nullptr )
     {
         stack2 . push ( p2 ) ;
         p2 = p2 -> next ;
     }
     while ( ! stack1 . empty ( ) &&! stack2 . empty() )
     {
         ListNode  * node1 = stack1 . top ( ) ;
         ListNode  * node2 = stack2 . top ( ) ;
         if ( node1 == node2 )
         {
              commonNode = node1 ;
              stack1 . pop ( ) ;
              stack2 . pop ( ) ;
         }
         else
         {
              break ;
         }
     }
     return  commonNode ;
}
public :
//
bool  isHasCommonNode ( ListNode  * head1 , ListNode  * head2 ) //notehead
{
     if ( head1 -> next == nullptr || head2 -> next == nullptr )
     {
         cout << "" << endl ;
              return  false ;
     }
     bool  cycle1 = hasCycle ( head1 -> next ) ;
     bool  cycle2 = hasCycle ( head2 -> next ) ;
     if (( cycle1 &&! cycle2 ) || ( ! cycle1 && cycle2 ))
     {
         cout << "" << endl ;
         return  false ;
     }
    
     if ( cycle1 && cycle2 )              
     {
         ListNode  * R1 = detectCycle ( head1 -> next ) ;
         R1 -> next = nullptr ;
         ListNode  * R2 = detectCycle ( head2 -> next ) ;
         R2 -> next = nullptr ;
        
         ListNode  * commonNode1 = findFristCommonNode2 ( head1 , head2 ) ;
         if ( commonNode1 != nullptr )
         {
              cout << ""  << endl ;
              cout << "" << commonNode1 -> val << endl ;
              return  true ;
         }
         else
         {
              cout << ""  << endl ;
              return  false ;
         }
     }
     if ( ! cycle1 &&! cycle2 )
     {
         ListNode  * commonNode2 = findFristCommonNode2 ( head1 , head2 ) ;
         if ( commonNode2 != nullptr )
         {
              cout << "均无"  << endl ;
              cout << "" << commonNode2 -> val << endl ;
              return  true ;
         }
         else
         {
              cout << ""  << endl ;
              return  false ;
         }
     }
     return  false ;
}
} ;
 
 
单链表之交换任意两个节点
对于单链表:
假设交换A、B两个节点,那么需要交换A与B的next指针以及A、B直接前驱的next指针。

需要考虑的情况:
1、当A与B相邻时,需做特殊处理;
2、当A与B元素相同时,没必要交换;
3、当A、B其中有一个头结点时,没必要交换;
4、一般情况:只需要找到节点的前驱,做相应的指针调整;

#include <iostream>
using  namespace  std ;
struct  ListNode
{
     int  val ;
     ListNode  * next ;
     ListNode ( int  x ) : val ( x ) , next ( nullptr ) { }
} ;
/***************************************************************************************************/
//
ListNode  * creat ( )
{
     ListNode  * head = new  ListNode ( -1 ) ;
     ListNode  * p = head ;
     ListNode  * node = nullptr ;
     int  x = 0 ;
     int  cycle = 1 ;
     while ( cycle )
     {
         cout << "please input the data:" << endl ;
         cin >> x ;
         if ( x != 0 )        //0
         {
              node = new  ListNode ( x ) ;
              p -> next = node ;
              p = node ;
         }
         else
              cycle = 0 ;
     }
     p -> next = nullptr ;   //
     //head=head->next;
     return  head ;
}
/***************************************************************************************************/
//
void  printList ( ListNode  * head )   //notehead
{
     if ( head -> next == nullptr )
     {
         cout << "list is empty!" << endl ;
         return  ;
     }
     ListNode  * p = head -> next ;
     int  index = 0 ;
     while ( p != nullptr )
     {
         cout << "" <<++ index << "" << p -> val << endl ;
         p = p -> next ;
     }
}
/***************************************************************************************************/
//i
ListNode  * searchNode ( ListNode  * head , int  pos ) //head
{
     if ( head -> next == nullptr || pos < 0 )
         return  nullptr ;
     if ( pos == 0 )
         return  head ;
     ListNode  * p = head -> next ;
     while ( -- pos )
     {
         p = p -> next ;
         if ( p == nullptr )
         {
              cout << "incorrect postion to search node!" << endl ;
              break ;
         }
     }
     return  p ;
}
/***************************************************************************************************/
//
  ListNode  * findPre ( ListNode  * head , ListNode  * node )
  {
      ListNode  * p = head ;
      while ( p -> next != node )
      {
          p = p -> next ;
      }
      return  p ;
  }
/***************************************************************************************************/
//
//
//1AB
//2AB
//3AB
//4
ListNode  * swap ( ListNode  * head , ListNode  * node1 , ListNode  * node2 ) //notehead
{
     if ( head -> next == nullptr || node1 == nullptr || node2 == nullptr )
     {
         cout << "invalid parameter:nullptr" << endl ;
         return  head ;
     }
     //
     if ( node1 == head || node2 == head )
         return  head ;
     //
     if ( node1 -> val == node2 -> val )
         return  head ;
     //
      ListNode  * preNode1 = findPre ( head , node1 ) ;
      ListNode  * postNode1 = node1 -> next ;
      ListNode  * preNode2 = findPre ( head , node2 ) ;
      ListNode  * postNode2 = node2 -> next ;
      if ( postNode1 == node2 )
      {
          node1 -> next = postNode2 ;
          preNode1 -> next = node2 ;
          node2 -> next = node1 ;
      }
      else  if ( postNode2 == node1 )
      {
          node2 -> next = postNode1 ;
          preNode2 -> next = node1 ;
          node1 -> next = node2 ;
      }
      //
      else  if ( node1 != node2 )
      {
          preNode1 -> next = node2 ;
          node2 -> next = postNode1 ;
          preNode2 -> next = node1 ;
          node1 -> next = postNode2 ;
      }
      return  head ;
}   
/**************************************************************************************************/
int  main ( )
{
     ListNode  * head = new  ListNode ( 0 ) ;
     head = creat ( ) ;
     cout << "" << endl ;
     printList ( head ) ;
     int  pos1 = 0 ;
     ListNode  * node1 = searchNode ( head , pos1 ) ;
     cout << "" << pos1 << "" << node1 -> val << endl ;
     int  pos2 = 6 ;
     ListNode  * node2 = searchNode ( head , pos2 ) ;
     cout << "" << pos2 << "" << node2 -> val << endl ;
     ListNode  * newHead = swap ( head , node1 , node2 ) ;
     cout << "" << endl ;
     printList ( newHead ) ;
    
     system ( "pause" ) ;
     return  0 ;
}
 

单链表之基本操作总结
 
 
#include <iostream>
#include <unordered_map>
#include <stack>
using  namespace  std ;
struct  ListNode
{
     int  val ;
     ListNode  * next ;
     ListNode ( int  x ) : val ( x ) , next ( nullptr ) { }
} ;
/**************/
//
ListNode  * creat ( )
{
     ListNode  * head = new  ListNode ( -1 ) ;
     ListNode  * p = head ;
     ListNode  * node = nullptr ;
     int  x = 0 ;
     int  cycle = 1 ;
     while ( cycle )
     {
         cout << "please input the data:" << endl ;
         cin >> x ;
         if ( x != 0 )        //0
         {
              node = new  ListNode ( x ) ;
              p -> next = node ;
              p = node ;
         }
         else
              cycle = 0 ;
     }
     p -> next = nullptr ;   //
     //head=head->next;
     return  head ;
}
/*****************/
//
void  printList ( ListNode  * head )   //notehead
{
     if ( head -> next == nullptr )
     {
         cout << "list is empty!" << endl ;
         return  ;
     }
     ListNode  * p = head -> next ;
     int  index = 0 ;
     while ( p != nullptr )
     {
         cout << "" <<++ index << "" << p -> val << endl ;
         p = p -> next ;
     }
}
/*********************/
//
int  getListLength ( ListNode  * head )   //notehead
{
     int  len = 0 ;
     ListNode  * p = head -> next ;
     while ( p != nullptr )
     {
         ++ len ;
         p = p -> next ;
        
     }
     return  len ;
}
/*************/
//
//dataii=pos
//i-1O(n)
//;ii0
ListNode  * insertList ( ListNode  * head , int  pos , int  data ) //notehead
{
      ListNode  * newNode = new  ListNode ( data ) ;
     
      ListNode  * p = head ;
      int  index = 1 ;
      while ( p != nullptr && index < pos )
      {
           p = p -> next ;
           ++ index ;
      }
      newNode -> next = p -> next ;
      p -> next = newNode ;
      return  head ;
}
/*******************/
//:i
//
//ni1=<i<=n,i=n+1
//
//ppindex<i
//On
ListNode  * deleteNode ( ListNode  * head , int  pos ) //pos11
    
{
         ListNode  * p = head ;
         if ( p -> next == nullptr )   //
         {
                cout << "" << endl ;
              return  nullptr ;
         }
         ListNode  * node = nullptr ;
         int  index = 1 ;
         while ( p != nullptr && index < pos )
         {
              p = p -> next ;
              ++ index ;
         }
         if ( p != nullptr && p -> next != nullptr )  
         {
         node = p -> next ;
         p -> next = node -> next ;
         delete  node ;
         }
         return  head ;
}
/*********************/
//i
ListNode  * searchNode ( ListNode  * head , int  pos ) //head
{
     if ( head -> next == nullptr || pos < 0 )
         return  nullptr ;
     if ( pos == 0 )
         return  head ;
     ListNode  * p = head -> next ;
     while ( -- pos )
     {
         p = p -> next ;
         if ( p == nullptr )
         {
              cout << "incorrect postion to search node!" << endl ;
              break ;
         }
     }
     return  p ;
}
/**********************/
//
//lenlen/2
//slowfastfast
//        slowfastslow
//        slowslow
ListNode  * searchMidNode ( ListNode  * head )
{
     if ( head -> next == nullptr )
         return  head ;
     ListNode  * slow = head -> next ;
     ListNode  * fast = head -> next ;
     while ( fast != nullptr && fast -> next != nullptr && fast -> next -> next != nullptr ) //lenslowslowmid
                                            //while(fast!=nullptr&&fast->next!=nullptr)lenslowslowmid                                                          
     {
         slow = slow -> next ;
         fast = fast -> next -> next ;
     }
     return  slow ;
}
/*************************/
// k
//lenlen-kk
//On;p1p2p2k-1p1p2
//        p2p1
ListNode  * searchReverseKthNode ( ListNode  * head , int  k )
{
     if ( head -> next == nullptr || k == 0 )
        return  head ;
    
     ListNode  * p1 = head -> next ;
     ListNode  * p2 = head -> next ;
     while ( p2 != nullptr &&-- k )
     {
         p2 = p2 -> next ;
     }
     while ( p2 -> next != nullptr )
     {
         p1 = p1 -> next ;
         p2 = p2 -> next ;
     }
     return  p1 ;  
}
/********************/
//
//                      
//
ListNode  * reverse ( ListNode  * head )
{
     if ( head -> next == nullptr && head -> next -> next == nullptr )
         return  head ;
     ListNode  * tail = head -> next ;
     ListNode  * cur = tail -> next ;
     while ( cur != nullptr )
     {
         //
         tail -> next = cur -> next ;
         //
         cur -> next = head -> next ;
         head -> next = cur ;
         //
         cur = tail -> next ;
     }
     return  head ;
}
//
//         
ListNode  * reverse2 ( ListNode  * head )
{
     if ( head -> next == nullptr )
         return  head ;
     ListNode  * pre = head -> next ;
     ListNode  * cur = pre -> next ;
     pre -> next = nullptr ;  //
     ListNode  * tmp = nullptr ;
     while ( cur != nullptr )
     {
         tmp = cur -> next ;
         cur -> next = pre ;
         pre = cur ;
         cur = tmp ;
     }
     head -> next = pre ; //  
     return  head ;
}
/****************/
//:
//
//        
//nn+1
//        nn+1
void  printListReversely ( ListNode  * head )
{
     if ( head -> next != nullptr )
     {
         printListReversely ( head -> next ) ;
         cout << head -> next -> val << endl ;
     }
}
/********************/
//
//head1head2head1head2,head2
//              head1head1head2head1
//              head1head2head1
//              >=head2head2
//               head1head2
//               
//               head1head2headhead2head1head;
//        使
ListNode  * mergeRecursive ( ListNode  * head1 , ListNode  * head2 ) //head1head2
{
    
     if ( head1 == nullptr )
         return  head2 ;
     if ( head2 == nullptr )
         return  head1 ;
     ListNode  * newHead = nullptr ;
     if ( head1 -> val < head2 -> val )
     {
    
         newHead = head1 ;
         newHead -> next = mergeRecursive ( head1 -> next , head2 ) ;
     }
     else
     {
         newHead = head2 ;
         newHead -> next = mergeRecursive ( head1 , head2 -> next ) ;
     }
     return  newHead ;    //
}                                                                            
// head1head2head1head2
//                 head1head2
//                  
ListNode  * mergeList ( ListNode  * head1 , ListNode  * head2 ) //head1head2
{
     ListNode  * newHead = new  ListNode ( 0 ) ;
     ListNode  * node = newHead ;
     while ( head1 != nullptr && head2 != nullptr )
     {
         if ( head1 -> val < head2 -> val )
         {
              node -> next = head1 ;
              node = head1 ;
              head1 = head1 -> next ;
         }
         else
         {
              node -> next = head2 ;
              node = head2 ;
              head2 = head2 -> next ;
         }
     }
     if ( head1 != nullptr )
     {
         node -> next = head1 ;
     }
     if ( head2 != nullptr )
     {
         node -> next = head2 ;
     }
     return  newHead ;  //
}
/********************/
//
//使hashO(n)O(n)
//  1hashkey
//  2
//     1hash
//     2hashhash
ListNode  *  deleteDuplicateFromUnsortedList ( ListNode  * head )
{
     if ( head -> next == nullptr && head -> next -> next == nullptr )
         return  head ;
      unordered_map < int , bool >  visited ( false ) ;
      ListNode  * pre = head ;
      ListNode  * cur = pre -> next ;
      ListNode  * tmp = nullptr ;
      while ( cur != nullptr )
      {
    
           if ( visited [ cur -> val ])
           {
              tmp = cur ;   //tmp
              pre -> next = cur -> next ;  //
              cur = cur -> next ;
              delete  tmp ;  //
           }
           else
           {
                visited [ cur -> val ] = true ;
                pre = pre -> next ;
                cur = cur -> next ;
           }
        
      }
      return  head ;
}
//使,O(n^2)
//       1cur
//       2ppcurcur
//       3tmptmp
//
ListNode  *  deleteDuplicateFromUnsortedList2 ( ListNode  * head )
{
       if ( head -> next == nullptr )
            return  head ;
       ListNode  * cur = head -> next ;
       ListNode  * p = nullptr ;
       ListNode  * tmp = nullptr ;
       while ( cur != nullptr )
       {
            p = cur ;
            while ( p -> next != nullptr )
            {
                 if ( p -> next -> val == cur -> val )
                 {
                      tmp = p -> next ;
                      p -> next = p -> next -> next ;
                      delete  tmp ;
                       
                 }
                 else
                 {
                      p = p -> next ;
                  }
             }
            cur = cur -> next ;
       }
       return  head ;
}
//
ListNode  *  deleteDuplicateFromUnsortedList3 ( ListNode  * head )
{
     if ( head -> next == nullptr )
         return  head ;
     ListNode  * tmp = head ;    //headtmphead
     head -> next = deleteDuplicateFromUnsortedList3 ( head -> next ) ; //head->nexthead
     ListNode  * cur = head -> next ; //curheadtmp=head
       while ( cur != nullptr )
       {
            if ( cur -> val == head -> val ) //headheadhead
            {
                 tmp -> next = cur -> next ;
                 delete  cur ;
                 cur = tmp -> next ;
            }
            else
            {
                 cur = cur -> next ;
                 tmp = tmp -> next ; //tempheadcurcurtmpheadcurtemp->nextcur
            }
       }
       return  head ;
}
/*************************/
//
     bool  hasCycle ( ListNode  * head )  //head
  {
      if ( head == nullptr )
           return  false ;
      ListNode  * slow = head ;
      ListNode  * fast = head ;
      while ( fast != nullptr && fast -> next != nullptr )
      {
           slow = slow -> next ;
           fast = fast -> next -> next ;
           if ( slow == fast )
                return  true ;
      }
      return  false ;
  }
/**********************/
     //
     ListNode  * detectCycle ( ListNode  * head ) //head
     {
         if ( head == nullptr )
              return  nullptr ;
         ListNode  * slow = head ;
         ListNode  * fast = head ;
         ListNode  * slow2 = head ;
         while ( fast != nullptr && fast -> next != nullptr )
         {
              slow = slow -> next ;
              fast = fast -> next -> next ;
              if ( fast == slow )
              {
                   while ( slow != slow2 )
                   {
                        slow = slow -> next ;
                        slow2 = slow2 -> next ;
                   }
                   return  slow2 ;
              }
         }
         return  nullptr ;
     }
/*********************/
//
//
ListNode  *  findFristCommonNode1 ( ListNode  * head1 , ListNode  * head2 )
{
     if ( head1 -> next == nullptr || head2 -> next == nullptr )
     {
         cout << "" << endl ;
              return  nullptr ;
     }
     ListNode  * p1 = head1 -> next ;
     ListNode  * p2 = head2 -> next ;
     while ( p1 != nullptr )
     {
         while ( p2 != nullptr )
         {
              if ( p1 == p2 )
              {
                   cout << "" << endl ;
                   return  p1 ;
              }
              else
                   p2 = p2 -> next ;
         }
         p1 = p1 -> next ;
     }
     return  nullptr ;
}
//+
     ListNode  *  findFristCommonNode2 ( ListNode  * head1 , ListNode  * head2 )
     {
         if ( head1 -> next == nullptr || head2 -> next == nullptr )
         {
              cout << "" << endl ;
              return  nullptr ;
           }
         int  len1 = getListLength ( head1 ) ;
         int  len2 = getListLength ( head2 ) ;
         int  k = len1 - len2 ;
         ListNode  * plong = nullptr ;
         ListNode  * pshort = nullptr ;
         if ( k > 0 )
         {
              plong = head1 -> next ;
              pshort = head2 -> next ;
              while ( k -- )
              {
                   plong = plong -> next ;
              }
         }
         else
         {
              plong = head2 -> next ;
              pshort = head1 -> next ;
              k = ( - k ) ;
              while ( k -- )
              {
                   plong = plong -> next ;
              }
         }
         while ( plong != nullptr && pshort != nullptr && plong != pshort )
         {
              plong = plong -> next ;
              pshort = pshort -> next ;
         }
         if ( plong == pshort )
              return  plong ;
         return  nullptr ;
     }
//
ListNode  *  findFristCommonNode3 ( ListNode  * head1 , ListNode  * head2 )
{
     if ( head1 -> next == nullptr || head2 -> next == nullptr )
     {
         cout << "" << endl ;
              return  nullptr ;
     }
    
     ListNode  * p = head1 -> next ;
     ListNode  * newHead = p ;
     while ( p -> next != nullptr )
     {
         p = p -> next ;
     }
     p -> next = head2 -> next ;
     if ( hasCycle ( newHead ))
     {
         return  detectCycle ( newHead ) ;
     }
     return  nullptr ;
}
//+
ListNode  *  findFristCommonNode4 ( ListNode  * head1 , ListNode  * head2 ) //notehead
{
     if ( head1 -> next == nullptr || head2 -> next == nullptr )
     {
         cout << "" << endl ;
              return  nullptr ;
     }
     stack < ListNode  *> stack1 ;
     stack < ListNode  *> stack2 ;
     ListNode  * p1 = head1 -> next ;
     ListNode  * p2 = head2 -> next ;
     ListNode  * commonNode = nullptr ;
     while ( p1 != nullptr )
     {
         stack1 . push ( p1 ) ;
         p1 = p1 -> next ;
     }
     while ( p2 != nullptr )
     {
         stack2 . push ( p2 ) ;
         p2 = p2 -> next ;
     }
     while ( ! stack1 . empty ( ) &&! stack2 . empty ( ))
     {
         ListNode  * node1 = stack1 . top ( ) ;
         ListNode  * node2 = stack2 . top ( ) ;
         if ( node1 == node2 )
         {
              commonNode = node1 ;
              stack1 . pop ( ) ;
              stack2 . pop ( ) ;
         }
         else
         {
              break ;
         }
     }
     return  commonNode ;
}
/****************************/
//
bool  isHasCommonNode ( ListNode  * head1 , ListNode  * head2 ) //notehead
{
     if ( head1 -> next == nullptr || head2 -> next == nullptr )
     {
         cout << "" << endl ;
              return  false ;
     }
     bool  cycle1 = hasCycle ( head1 -> next ) ;
     bool  cycle2 = hasCycle ( head2 -> next ) ;
     if (( cycle1 &&! cycle2 ) || ( ! cycle1 && cycle2 ))
     {
         cout << "" << endl ;
         return  false ;
     }
    
     if ( cycle1 && cycle2 )              
     {
         ListNode  * R1 = detectCycle ( head1 -> next ) ;
         R1 -> next = nullptr ;
         ListNode  * R2 = detectCycle ( head2 -> next ) ;
         R2 -> next = nullptr ;
        
         ListNode  * commonNode1 = findFristCommonNode2 ( head1 , head2 ) ;
         if ( commonNode1 != nullptr )
         {
              cout << ""  << endl ;
              cout << "" << commonNode1 -> val << endl ;
              return  true ;
         }
         else
         {
              cout << ""  << endl ;
              return  false ;
         }
     }
     if ( ! cycle1 &&! cycle2 )
     {
         ListNode  * commonNode2 = findFristCommonNode2 ( head1 , head2 ) ;
         if ( commonNode2 != nullptr )
         {
              cout << ""  << endl ;
              cout << "" << commonNode2 -> val << endl ;
              return  true ;
         }
         else
         {
              cout << ""  << endl ;
              return  false ;
         }
     }
     return  false ;
}
/*********************/

int  main ( )
{
     /*
    ListNode *head=new ListNode(0);
    head=creat();
    cout<<""<<endl;
    printList(head);
    int len=getListLength(head);
    cout<<""<<len<<endl;
    
    int pos=1;
    int data=50;
    insertList(head,pos,data);
    cout<<""<<endl;
    printList(head);
    
    
    int i=5;
    deleteNode(head, i);
    cout<<""<<endl;
    printList(head);
    
    int pos2=0;
    ListNode *snode=searchNode(head,pos2);
    cout<<";"<<snode->val<<endl;
    
    ListNode *mid=searchMidNode(head);
    cout<<""<<mid->val<<endl;
    
    int k=1;
    ListNode *kNode=searchReverseKthNode(head,k);
    cout<<"k"<<kNode->val<<endl;
    
    ListNode *rhead=reverse(head);
    cout<<""<<endl;
    printList(head);
    
    ListNode *rhead=reverse2(head);
    cout<<""<<endl;
    printList(head);
    
    cout<<""<<endl;
    printListReversely(head);
    */
    
     /*
    ListNode *head1=new ListNode(0);
    head1=creat();
    cout<<""<<endl;
    printList(head1);
    ListNode *head2=new ListNode(0);
    head2=creat();
    cout<<""<<endl;
    printList(head2);
    
    ListNode *newHead=new ListNode(0);
    newHead=mergeRecursive(head1->next,head2->next);
    cout<<""<<endl;
    ListNode *newHead1=new ListNode(0);
    newHead1->next=newHead;
    printList(newHead1);
    */
     /*
    ListNode *head3=new ListNode(0);
    head3=creat();
    cout<<""<<endl;
    printList(head3);
    ListNode *head4=new ListNode(0);
    head4=creat();
    cout<<""<<endl;
    printList(head4);
    ListNode *newHead2=new ListNode(0);
    newHead2=mergeList(head3->next,head4->next);
    cout<<"2"<<endl;
    printList(newHead2);
    */
    
     /*
    ListNode *head5=new ListNode(0);
    head5=creat();
    cout<<""<<endl;
    printList(head5);
    ListNode *newHead5=new ListNode(0);
    newHead5=deleteDuplicateFromUnsortedList(head5);
    cout<<"1"<<endl;
    printList(newHead5);
    */
     /*
    ListNode *head6=new ListNode(0);
    head6=creat();
    cout<<""<<endl;
    printList(head6);
    ListNode *newHead6=new ListNode(0);
    newHead6=deleteDuplicateFromUnsortedList2(head6);
    cout<<"2"<<endl;
    printList(newHead6);
    */
    
     /*
    ListNode *head7=new ListNode(0);
    head7=creat();
    cout<<""<<endl;
    printList(head7);
    ListNode *newHead7=new ListNode(0);
    newHead7=deleteDuplicateFromUnsortedList3(head7);
    cout<<"3"<<endl;
    printList(newHead7);
    */
    
    /*
    ListNode *head3=new ListNode(0);
    head3=creat();
    cout<<""<<endl;
    printList(head3);
    ListNode *head1=new ListNode(0);
    head1=creat();
    ListNode *newHead1=head1;
    while(head1->next!=nullptr)
    {
         head1=head1->next;
    }
    head1->next=head3->next;
    cout<<""<<endl;
    printList(newHead1);
    ListNode *head2=new ListNode(0);
    head2=creat();
    ListNode *newHead2=head2;
    while(head2->next!=nullptr)
    {
         head2=head2->next;
    }
    head2->next=head3->next;
    cout<<""<<endl;
    printList(newHead2);
    
    ListNode *newHead7=new ListNode(0);
    newHead7=findFristCommonNode1(head1,head2);
    if(newHead7!=nullptr)
         cout<<""<<newHead7->val;
    else
         cout<<"no!"<<endl;
         
    bool hasCom=isHasCommonNode(head1,head2);
    if(hasCom)
         cout<<"yes"<<endl;
    else
         cout<<"No!"<<endl;
    */
   
   
    system ( "pause" ) ;
     return  0 ;
}
 
单循环链表
 循环链表是首尾相接的链表,他与单链表的唯一区别在于对尾节点的处理,在单链表中尾节点的指针域nullptr改为指向头结点就得到了单循环链表。

在单循环链表上的操作基本与非循环链表相同,只是将原来判断指针是否为nullptr变为是否是头指针,没有其他较大变化。

单向循环链表与单向链表相比,其尾结点的下一个结点指向首元素,这样就构成了一个环:

 
 


对于单链表只能从头节点开始遍历整个链表,而对于单循环链表则可以从表中任意节点开始遍历整个链表。因为有时对链表常做的操作在表尾、表头进行,此时改变一下链表的标识方法,不用头指针而用一个指向尾节点的rear来标识,可以使操作效率得以提高。

1、用尾指rear标识的单循环链表查找开始节点和尾节点很方便,此时查找时间复杂度均为O(1)。 

2、对单循环链表H1和H2的连接操作,是将H2的第一个数据节点接到H1的尾节点,若用头指针标识,则需要找到第一个链表的尾节点,其时间复杂度为O(n);而表若用尾指针R1、R2来标识,则时间复杂度为O(1)。
 
p = R1 -> next ;  //R1
R1 -> next = R2 -> next -> next ; //
delete  R2 -> next ; //
R2 -> next = p ; //

 
// 
  void  deletePreNodeInSingleLoopList ( ListNode  * head , ListNode  * s )
  {
      if ( head == nullptr || head -> next == nullptr )
          return ;
      ListNode  * p = s ;
      ListNode  * q = nullptr ;
      while ( p -> next -> next != s )
      {
          q = p ;
          p = p -> next ;
      }
      q -> next = s ;
      delete  p ;
  }
 
 
 


  


单循环链表之约瑟夫问题1
 
 
// 1,2...NN
//M1MM
//M
#include  <iostream>
using  namespace  std ;
struct  ListNode 
{
     int  val ;
     ListNode  * next ;
     ListNode ( int  x ) : val ( x ) , next ( nullptr ) { }
} ;
//n
ListNode  *  creatSingleLoopList ( int  n )       //
{
     ListNode  * rear = nullptr ;
     if ( n != 0 )
     {
         ListNode  * beginNode = new  ListNode ( -1 ) ;
         rear = beginNode ;
        
         int  value = 1 ;
         ListNode  * node = nullptr ;
         while ( value <= n )
         {
              node = new  ListNode ( value ) ;
              rear -> next = node ;
              node -> next = beginNode ;
              rear = node ;
              ++ value ;
         }
         rear -> next = beginNode -> next ;
         delete  beginNode ;
     }
    
     return  rear ;
}
void  printSingleLoopList ( ListNode  * rear )  // //
{
     if ( rear -> next == nullptr )
     {
         cout << "list is empty!" << endl ;
     }
     ListNode  * p = rear ;
     int  i = 1 ;
     while ( p -> next != rear )
     {
         p = p -> next ;
         cout << i ++<< ":" << p -> val << endl ;
    
     }
     p = p -> next ;   //
     cout << i ++<< ":" << p -> val << endl ;
}
int  main ( )
{
     /*
    int n=15;
    ListNode *rear=creatSingleLoopList (n);
    printSingleLoopList(rear);\
    */
    
     int  n = 10 ;
     int  m = 6 ;
     ListNode  * rear = creatSingleLoopList  ( n ) ;
     printSingleLoopList ( rear ) ;
     ListNode  * prear = creatSingleLoopList  ( n ) ;
     ListNode  * pcur = prear -> next ;  
     m %= n ;
     while ( pcur != pcur -> next )
     {
         for ( int  i = 1 ; i < m -1 ; ++ i )
         {
              pcur = pcur -> next ;
         }
         cout << pcur -> next -> val << endl ; //m
           //m=pcur->next->val;    //mMM
         //m
         ListNode  * tmp = pcur -> next ;
         pcur -> next = pcur -> next -> next ;
         pcur = pcur -> next ;
         delete  tmp ;
     }
     cout << pcur -> val << endl ;  //
    
    
     system ( "pause" ) ;
     return  0 ;
}
双向链表之基本操作
 
双向链表与单向链表相比,各个结点多了一个指向前一个结点的指针。结构如图所示:


 
#include <iostream>
using  namespace  std ;
struct  ListNode
{
     int  val ;
     ListNode  * prior ;
     ListNode  * next ;
     ListNode ( int  x ) : val ( x ) , prior ( nullptr ) , next ( nullptr ) { }
} ;
//
  ListNode  * creatDList ( )
  {
      ListNode  * beginNode = new  ListNode ( -1 ) ;
      beginNode -> prior = nullptr ;
      beginNode -> next = nullptr ;
      ListNode  * p = beginNode ;
      int  x = 0 ;
      int  cycle = 1 ;
      while ( cycle )
      {
         cout << "please input the data:" << endl ;
         cin >> x ;
         if ( x != 0 )        //0
         {
              ListNode  * node = new  ListNode ( x ) ;
              p -> next = node ;
              node -> prior = p ;
              node -> next = nullptr ;
              p = node ;
             
         }
         else
              cycle = 0 ;
     }
    
     return  beginNode ;
  }
  //
  void  printDList ( ListNode  * head )
  {
      if ( head -> next == nullptr )
      {
          cout << "list is empty!" << endl ;
          return ;
      }
      ListNode  * q = head -> next ;
      int  index = 1 ;
      while ( q != nullptr )
      {
          cout << index ++<< "" << q -> val << endl ;
          q = q -> next ;
      }
  }
  //
  int  getDListLength ( ListNode  * head )
  {
      if ( head -> next == nullptr )
      {
          cout << "list is empty!" << endl ;
          return  0 ;
      }
      int  index = 0 ;
      ListNode  * p = head -> next ;
      while ( p != nullptr )
      {
          ++ index ;
          p = p -> next ;
      }
      return  index ;
  }
  //
  bool  isEmpty ( ListNode  * head )
  {
      if ( head -> prior == head -> next )
          return  true ;
      else
          return  false ;
  }
  //i
  //使next
ListNode  * searchNode ( ListNode  * head , int  pos )
{
     if ( head -> next == nullptr || pos < 0 )
         return  nullptr ;
     if ( pos == 0 )
         return  head ;
     ListNode  * p = head -> next ;
     while ( -- pos )
     {
         p = p -> next ;
         if ( p == nullptr )
         {
              cout << "incorrect postion to search node!" << endl ;
              break ;
         }
     }
     return  p ;
}
//dataii=pos
//
ListNode  * insertDList ( ListNode  * head , int  pos , int  data )
{
      int  len = getDListLength ( head ) ;
      ListNode  * newNode = new  ListNode ( data ) ;
      ListNode  * p = nullptr ;
      if ( pos == 0 )   //
      {
          newNode -> next = head -> next ;
          newNode -> prior = head ;
          head -> next -> prior = newNode ;
          head -> next = newNode ;
         }
      else  if ( pos > 0 && pos < len +1 ) //
      {
          p = searchNode ( head , pos -1 ) ;  //i-1
          newNode -> next = p -> next ;
          newNode -> prior = p ;
          p -> next -> prior = newNode ;
          p -> next = newNode ;
      }
      else  if ( pos == len +1 )  //
      {
          p = searchNode ( head , pos -1 ) ;
          newNode -> next = nullptr ;
          newNode -> prior = p ;
          p -> next = newNode ;
      }
      else   //
      {
        cout << "incorrect postion to insert node!" << endl ;
      }
      return  head ;
}
//i
//
//ni1=<i<=n,i=n+1
//
ListNode  * deleteNode ( ListNode  * head , int  pos )
{
     ListNode  * p = searchNode ( head , pos ) ; //i
     if ( p == nullptr )  //
     {
         cout << "incorrect postion to delete node!" << endl ;
     }
    
     else  if ( p -> prior == nullptr ) //
     {
         if ( p -> next != nullptr ) //
         {
           p -> next -> prior = nullptr ;
           ListNode  * newBeginNode = new  ListNode ( -2 ) ;
            newBeginNode -> next = p -> next ;
           delete  p ;
           return  newBeginNode ;
         }
     }
    
     else  if ( p -> next == nullptr ) // 
     {
         p -> prior -> next = nullptr ;
         delete  p ;
     }
     else    //
     {
         p -> prior -> next = p -> next ;
         p -> next -> prior = p -> prior ;
         delete  p ;
     }
     return  head ;
}
//
void  clearDList ( ListNode  * head )
{
     ListNode  * tmp = nullptr ;
     ListNode  * p = head -> next ;
     while ( p != nullptr )
     {
         tmp = p -> next ;
         delete  p ;
         p = tmp ;
     }
     head -> next = head -> prior = nullptr ;
}
//
void  printReversely ( ListNode  * head )
{
     if ( head -> next != nullptr )
      {
          int  index = 1 ;
          printReversely ( head -> next ) ;
          cout << index ++<< "" << head -> next -> val << endl ;
     }
     else
         cout << "list is empty!" << endl ;
}
  int  main ( )
  {
      ListNode  * head = creatDList ( ) ;
      cout << "" << endl ;
      printDList ( head ) ;
      int  len = getDListLength ( head ) ;
      cout << "" << len << endl ;
     
      int  pos1 = 7 ;
      ListNode  * sNode = searchNode ( head , pos1 ) ;
      if ( sNode != nullptr )
      {
        cout << "" << pos1 << "" << sNode -> val << endl ;
      }
     
      int  pos2 = 7 ;
      int  data = 88 ;
      ListNode  * head1 = insertDList ( head , pos2 , data ) ;
      cout << "" << endl ;
      printDList ( head1 ) ;
     
      int  pos3 = 0 ;
      ListNode  * head2 = deleteNode ( head , pos3 ) ;
      cout << "" << endl ;
      printDList ( head2 ) ;
      //
      if ( pos3 == 0 )
      {
         cout << endl ;
         cout << head2 -> val ;
      }
     
      bool  flag = isEmpty ( head ) ;
      if ( flag )
      {
          cout << "list is empty!" << endl ;
      }
      else
     {
          cout << "list is not empty!" << endl ;
      }
     
      clearDList ( head ) ;
      cout << "" << endl ;
      printDList ( head ) ;
     
      cout << "" << endl ;
      printReversely ( head ) ;
      cout << "" << endl ;
      printDList ( head ) ;
      system ( "pause" ) ;
      return  0 ;
  }


  • 13
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值