链表中倒数第K个结点

Posted 三颗心

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了链表中倒数第K个结点相关的知识,希望对你有一定的参考价值。

题目:输入一个链表,输出该链表中倒数第K个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,从头结点开始它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个结点是值为4的结点。

思路:设定两个指针p1和p2,两个指针刚开始都指向链表的第一个结点,然后让p1指针先走(k-1)步,然后再让两个指针一起往后走,当p1指针指向链表最后一个结点的时候,p2指针刚好指向链表中的倒数第k个结点。

在写代码的时候需要考虑鲁棒性,最好采用防御性编程,就是考虑在哪些地方会出错,然后提前加上错误判断,这样避免因此错误输入而导致程序崩溃。

  1 #include<iostream>
  2 #include<stdio.h> 
  3 #include<tchar.h>
  4 using namespace std;
  5 
  6 //链表结构
  7 struct ListNode
  8 {
  9     int m_nValue;
 10     ListNode* m_pNext;
 11 };
 12 
 13 //创建一个链表结点
 14 ListNode* CreateListNode(int value)
 15 {
 16     ListNode* pNode = new ListNode();
 17     pNode->m_nValue = value;
 18     pNode->m_pNext = NULL;
 19 
 20     return pNode;
 21 }
 22 
 23 //输出链表中的某一结点的值
 24 void PrintListNode(ListNode* pNode)
 25 {
 26     if(pNode == NULL)
 27             printf("The node is NULL\\n");
 28     else
 29             printf("The key in node is %d.\\n", pNode->m_nValue);
 30 }
 31 
 32 //输出链表 
 33 void PrintList(ListNode* pHead)
 34 {
 35     ListNode *pNode = pHead;
 36     while(pNode != NULL)
 37     {
 38         cout << pNode->m_nValue<< " ";
 39         pNode = pNode->m_pNext;
 40     }
 41     cout<<endl;
 42 }
 43 
 44 //删除结点 
 45 void DestroyList(ListNode* pHead)
 46 {
 47     ListNode* pNode = pHead;
 48     while(pNode != NULL)
 49     {
 50         pHead = pHead->m_pNext;
 51         delete pNode;
 52         pNode = pHead;
 53     }
 54 }
 55 
 56 //往链表末尾添加结点
 57 /*
 58 注意这里pHead是一个指向指针的指针,在主函数中一般传递的是引用。
 59 因为如果要为链表添加结点,那么就会修改链表结构,所以必须传递引用才能够保存修改后的结构。
 60 */
 61 void AddToTail(ListNode** pHead, int value)
 62 {
 63     ListNode* pNew = new ListNode();
 64     pNew->m_nValue = value;
 65     pNew->m_pNext = NULL;
 66 
 67     if(*pHead == NULL)
 68     {
 69         *pHead = pNew;
 70     }
 71     else
 72     {
 73         ListNode* pNode = *pHead;
 74         while(pNode->m_pNext != NULL)
 75             pNode = pNode->m_pNext;
 76 
 77         pNode->m_pNext = pNew;
 78     }
 79 }
 80 
 81 
 82 //链接两个结点 
 83 //void ConnectListNodes(ListNode* pCurrent, ListNode* pNext)
 84 //{
 85 //    if(pCurrent == NULL)
 86 //    {
 87 //        printf("Error to connect two nodes.\\n");
 88 //        exit(1);
 89 //    }
 90 //    pCurrent->m_pNext = pNext;
 91 //}
 92 
 93 //防御性编程,鲁棒性更好
 94 ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
 95 {
 96     if(pListHead == NULL || k == 0)
 97             return NULL;
 98 
 99     ListNode *pAhead = pListHead;
100     ListNode *pBehind = NULL;
101 
102     for(unsigned int i = 0 ; i < k- 1 ; i ++)
103     {
104         if(pAhead->m_pNext != NULL)
105             pAhead = pAhead->m_pNext;
106         else
107             return NULL;
108     }
109     
110     pBehind = pListHead;
111     while(pAhead->m_pNext != NULL)
112     {
113         pAhead = pAhead->m_pNext;
114         pBehind = pBehind->m_pNext;
115     }
116 
117     return pBehind;
118 }
119 
120 int main()
121 {
122     //创建结点
123     ListNode* pNode1=CreateListNode(1);//创建一个结点
124     PrintList(pNode1);//打印
125     //往链表中添加新结点
126     AddToTail(&pNode1, 2);//为链表添加一个结点
127     AddToTail(&pNode1, 3);//为链表添加一个结点
128     AddToTail(&pNode1, 4);//为链表添加一个结点
129     AddToTail(&pNode1, 5);//为链表添加一个结点
130     AddToTail(&pNode1, 6);//为链表添加一个结点
131     AddToTail(&pNode1, 7);//为链表添加一个结点
132     //打印链表
133     PrintList(pNode1);//打印
134     //反转链表
135     ListNode* KthNode=FindKthToTail(pNode1,3);
136 
137     PrintListNode(KthNode);
138 
139     DestroyList(pNode1);
140     
141     return 0;
142 }

以上是关于链表中倒数第K个结点的主要内容,如果未能解决你的问题,请参考以下文章

剑指 14. 代码的鲁棒性链表中倒数第k个结点

链表中倒数第k个结点

高质量代码-链表中倒数第k个结点

剑指offer:链表中倒数第k个结点

链表中倒数第k个结点-剑指Offer

链表中倒数第k个结点