单链表核心代码

暂时忽略特例情况

1 单链表逆置

 // 利用两个指针变量存储当前节点和下一个节点的值

 link h=null;//第一个节点指针域置null 

 while(p) //p是头指针

{

   link tmp=p;//指向一个节点

   p=p->next;//把p指向第二个节点

   //给第一个节点指针域附值

   p->next=h;

   h=tmp;//存储下一个将要存储的地址 

}

  p=h;//赋给头指针

2 判断链表循环链接

//利用一快一慢,如果是环,则会相遇

while (fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;

        if (fast == slow)
        {
            return 1;
        }
    }

3 寻找链表中的中间元素

// 通过一个1步长,一个2步长,进行定位

while (1)
    {
        if (NULL == fast->next || NULL == fast->next->next)
        {
            return slow;
        }

        slow = slow->next;
        fast = fast->next->next;

        /* Prevent that there is a loop in the linked list. */
        if (fast == slow)
        {
            return NULL;
        }
    }

4 删除链表倒数第m个元素

//两种思路:1.先计算链表长度,然后n-m,遍历二次链表

           2.设置头尾两个指针,间隔m个元素,同步向前移动,当尾指针到末尾时,头指针即为所需元素  

  list ahead = sll;
    list after = sll;

    if (NULL == ahead || m <= 0)
    {
        return NULL;
    }

    while (m--)
    {
        if (NULL == ahead)
        {
            return NULL;
        }
        ahead = ahead->next;

        if (fast && fast->next)
        {
            fast = fast->next->next;
            if (fast == ahead)
            {
                return NULL;
            }
        }
    }

    while (1)
    {
        if (NULL == ahead)
        {
            return after;
        }
        ahead = ahead->next;
        after = after->next;

        if (fast && fast->next)
        {
            fast = fast->next->next;
            if (fast == ahead)
            {
                return NULL;
            }
        }
    }

5 判断一个链表部分是否是循环列表,如果是,找出其中开始相交的节点

//两种方法:1.增加一个额外数组,保留所有经过的指针,每经过一个,比较是否出现过,时间复杂度O(n),空间复杂度O(n)

           2.利用两个指针,一个步长1,一个步长2,当第一次相遇的时候,另一个指针指向链表头,另一个继续,步长都为1,当相遇时刻则为交点节点处。

给出2的代码实现:

    list slow = sll;
    list fast = sll;

    if (NULL == fast)
    {
        return NULL;
    }

    while (1)
    {
        if (NULL == fast->next || NULL == fast->next->next)
        {
            return NULL;
        }

        slow = slow->next;
        fast = fast->next->next;

        if (fast == slow)
        {
            slow = sll;
            break;
        }
    }

    while (1)
    {
        slow = slow->next;
        fast = fast->next;

        if (fast == slow)
        {
            return fast;
        }
    }

6 给定链表的头指针和一个结点指针,在O(1) 时间删除该结点

// 分情况,当节点是最后一个节点时,遍历删除;

   如果是中间节点,找到该节点的下一个,用下一个节点覆盖要删的节点

void DeleteNode(ListNode* pListHead, ListNode* pToBeDeleted)

{

      if(!pListHead || !pToBeDeleted)

            return;

 

      // if pToBeDeleted is not the last node in the list

      if(pToBeDeleted->m_pNext != NULL)

      {

            // copy data from the node next to pToBeDeleted

            ListNode* pNext = pToBeDeleted->m_pNext;

            pToBeDeleted->m_nKey = pNext->m_nKey;

            pToBeDeleted->m_pNext = pNext->m_pNext;

 

            // delete the node next to the pToBeDeleted

            delete pNext;

            pNext = NULL;

      }

      // if pToBeDeleted is the last node in the list

      else

      {

            // get the node prior to pToBeDeleted

            ListNode* pNode = pListHead;

            while(pNode->m_pNext != pToBeDeleted)

            {

                  pNode = pNode->m_pNext;            

            }

 

            // deleted pToBeDeleted

            pNode->m_pNext = NULL;

            delete pToBeDeleted;

            pToBeDeleted = NULL;

      }

} 

7 两个单向链表,找出它们的第一个公共结点

//两种方式:1.遍历A列表,对每个A元素,与B中元素依次比较,如果相同则为,则为相交节点,时间复杂度O(m*n)

                 2.先得到两个列表A,B的长度,如果len(A)- len(B)=k,先A列表遍历K个元素,然后,A,B列表同步前进,当相遇的时刻,即为相交节点处。

                    时间复杂度:O(2(M+N))等于O(M+N)

///////////////////////////////////////////////////////////////////////

// Find the first common node in the list with head pHead1 and

// the list with head pHead2

// Input: pHead1 - the head of the first list

//        pHead2 - the head of the second list

// Return: the first common node in two list. If there is no common

//         nodes, return NULL

///////////////////////////////////////////////////////////////////////

ListNode * FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2)

{

      // Get the length of two lists

      unsigned int nLength1 = ListLength(pHead1);

      unsigned int nLength2 = ListLength(pHead2);

      int nLengthDif = nLength1 - nLength2;

 

      // Get the longer list

      ListNode *pListHeadLong = pHead1;

      ListNode *pListHeadShort = pHead2;

      if(nLength2 > nLength1)

      {

            pListHeadLong = pHead2;

            pListHeadShort = pHead1;

            nLengthDif = nLength2 - nLength1;

      }

 

      // Move on the longer list

      for(int i = 0; i < nLengthDif; ++ i)

            pListHeadLong = pListHeadLong->m_pNext;

 

      // Move on both lists

      while((pListHeadLong != NULL) &&

            (pListHeadShort != NULL) &&

            (pListHeadLong != pListHeadShort))

      {

            pListHeadLong = pListHeadLong->m_pNext;

            pListHeadShort = pListHeadShort->m_pNext;

      }

 

      // Get the first common node in two lists

      ListNode *pFisrtCommonNode = NULL;

      if(pListHeadLong == pListHeadShort)

            pFisrtCommonNode = pListHeadLong;

 

      return pFisrtCommonNode;

}

 

///////////////////////////////////////////////////////////////////////

// Get the length of list with head pHead

// Input: pHead - the head of list

// Return: the length of list

///////////////////////////////////////////////////////////////////////

unsigned int ListLength(ListNode* pHead)

{

      unsigned int nLength = 0;

      ListNode* pNode = pHead;

      while(pNode != NULL)

      {

            ++ nLength;

            pNode = pNode->m_pNext;

      }

 

      return nLength;

}

原文地址:https://www.cnblogs.com/wwwfj/p/3215132.html