简单链表

参考:http://zhedahht.blog.163.com/

  1. 输入一个链表的头结点,从尾到头反过来打印出每个节点的值。
  2. 给定单向链表的头结点和一个结点指针,定义一个函数在O(1)时间删除该结点。
  3. 输入一个单链表的,输出该链表中倒数第k个结点。
  4. 定义一个函数,输入一个链表的头结点,反转该链表并输出反转链表的头结点。

1、思路:

  递归方式:利用栈的“先入后出”的特性,轻松解决。这里提供一个递归方法来模拟栈。

《简单链表》
《简单链表》
PrintListReverse

1 void PrintListReverse(ListNode* head)
2 {
3     if (head != NULL)
4     {
5         PrintListReverse(head->pNext);
6         printf("%d\t", head->nValue);
7     }
8 }

  非递归方式:直接利用栈。

《简单链表》
《简单链表》

 1 void PrintReverseIter(ListNode* pHead)
 2 {
 3     std::stack<ListNode*> nodes;
 4     ListNode* pNode = pHead;
 5     while (pNode != NULL)
 6     {
 7         nodes.push(pNode);
 8         pNode = pNode->m_pNext;
 9     }
10 
11     while (!nodes.empty())
12     {
13         pNode = nodes.top();
14         printf("%d\t", pNode->m_nValue);
15         nodes.pop();
16     }
17     printf("\n");
18 }

PrintReverseIter

 

2、思路:

  常用算法需要记录删除结点node的前一个结点pre,因为需要把node的后一个结点next赋给pre->pNext,不让单链表断裂,这样就需要从头遍历链表,时间复杂度为O(n)。换个角度,将next的内容覆盖node,删除next结点,这样假象删除node。涉及到node->pNext->pNext,所以需要分情况讨论,看是删除的是尾结点,如果是尾结点,就没有node->pNext->pNext,只能从头遍历链表。

《简单链表》
《简单链表》
DeleteNode

 1 void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted)
 2 {
 3     if(!pListHead || !pToBeDeleted)
 4         return;
 5 
 6     // 要删除的结点不是尾结点
 7     if(pToBeDeleted->m_pNext != NULL)
 8     {
 9         ListNode* pNext = pToBeDeleted->m_pNext;
10         pToBeDeleted->m_nValue = pNext->m_nValue;
11         pToBeDeleted->m_pNext = pNext->m_pNext;
12  
13         delete pNext;
14         pNext = NULL;
15     }
16     // 链表只有一个结点,删除头结点(也是尾结点)
17     else if(*pListHead == pToBeDeleted)
18     {
19         delete pToBeDeleted;
20         pToBeDeleted = NULL;
21         *pListHead = NULL;
22     }
23     // 链表中有多个结点,删除尾结点
24     else
25     {
26         ListNode* pNode = *pListHead;
27         while(pNode->m_pNext != pToBeDeleted)
28         {
29             pNode = pNode->m_pNext;            
30         }
31  
32         pNode->m_pNext = NULL;
33         delete pToBeDeleted;
34         pToBeDeleted = NULL;
35     }
36 }

 

3、思路:

  设置两个指针,相隔k-1个,这样后指针到达结尾,那么前指针就到达了前k个结点。注意,要保证链表长度超过k个,在预处理后指针时要做出判断。

《简单链表》
《简单链表》
FindKthToTail

 1 ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
 2 {
 3     if(pListHead == NULL || k == 0)
 4         return NULL;
 5 
 6     ListNode *pAhead = pListHead;
 7     ListNode *pBehind = NULL;
 8 
 9     for(unsigned int i = 0; i < k - 1; ++ i)
10     {
11         if(pAhead->m_pNext != NULL)
12             pAhead = pAhead->m_pNext;
13         else
14         {
15             return NULL;
16         }
17     }
18 
19     pBehind = pListHead;
20     while(pAhead->m_pNext != NULL)
21     {
22         pAhead = pAhead->m_pNext;
23         pBehind = pBehind->m_pNext;
24     }
25 
26     return pBehind;
27 }

 

4、思路:

  递归方式:有点难理解。

《简单链表》
《简单链表》

 1 ListNode* ReverseRecursive(ListNode* head)
 2 {
 3     if (head == NULL || head->m_pNext == NULL)
 4         return head;
 5     ListNode *curr, *next, *tail;
 6     curr = head;
 7     next = head->m_pNext;
 8 
 9     tail = ReverseRecursive(next);
10 
11     next->m_pNext = curr;
12     curr->m_pNext = NULL;
13     return tail;
14 }

ReverseRecursive

   非递归方式:留意结点移动的界限,移动到尾结点停止。

《简单链表》
《简单链表》
ReverseList

 1 ListNode* ReverseList(ListNode* pHead)
 2 {
 3     ListNode* pReversedHead = NULL;
 4     ListNode* pNode = pHead;
 5     ListNode* pPrev = NULL;
 6     while(pNode != NULL)
 7     {
 8         ListNode* pNext = pNode->m_pNext;
 9 
10         if(pNext == NULL)
11             pReversedHead = pNode;
12 
13         pNode->m_pNext = pPrev;
14 
15         pPrev = pNode;
16         pNode = pNext;
17     }
18 
19     return pReversedHead;
20 }

 

    原文作者:算法小白
    原文地址: https://www.cnblogs.com/wangpengjie/archive/2013/04/09/3011327.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞