如果遍历的话,需要遍历两次,如果用两个指针的话,只需要一次,同时需要注意代码的鲁棒性,本例子很具有代表性。代码如下:
(画图可以帮助理解)
#include <iostream>
#include <cstdlib>
using namespace std;
struct ListNode
{
int m_nValue;
ListNode *m_pNext;
};
//创建链表
ListNode *CreateListNode(int value)
{
ListNode *pNode = new ListNode();
pNode->m_nValue = value;
pNode->m_pNext = NULL;
return pNode;
}
//连接结点
void ConnectListNodes(ListNode *pCurrent, ListNode *pNext)
{
if (pCurrent == NULL)
{
cout << "Error to connect two nodes" << endl;
exit(1);
}
pCurrent->m_pNext = pNext;
}
//打印
void PrintListNode(ListNode *pNode)
{
if (pNode == NULL)
{
cout << "The node is NULL" << endl;
}
else
{
printf("The key in node is %d.\n", pNode->m_nValue);
}
}
//销毁
void DestroyList(ListNode *pHead)
{
ListNode *pNode = pHead;
while (pNode != NULL)
{
pHead = pHead->m_pNext;
delete pNode;
pNode = pHead;
}
}
//特别需要注意代码的鲁棒性
ListNode *FindKthToTail(ListNode *pListHead, int k)
{
//第一个地方
if (pListHead == NULL || k == 0)
{
return NULL;
}
//第一个指针
ListNode *pAHead = pListHead;
//第二个指针
ListNode *pBehind = NULL;
//第二个地方
for (unsigned int i = 0; i < k - 1;i++)
{
//第三个地方
if (pAHead->m_pNext != NULL)
{
//第一个指针先走k-1步
pAHead = pAHead->m_pNext;
}
else
{
return NULL;
}
}
pBehind = pListHead;
while (pAHead->m_pNext != NULL)
{
//从第k步开始,两个指针一起走
pAHead = pAHead->m_pNext;
pBehind = pBehind->m_pNext;
}
return pBehind;
}
// ====================测试代码====================
// 测试要找的结点在链表中间
void Test1()
{
printf("=====Test1 starts:=====\n");
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
printf("expected result: 4.\n");
ListNode* pNode = FindKthToTail(pNode1, 2);
PrintListNode(pNode);
DestroyList(pNode1);
}
// 测试要找的结点是链表的尾结点
void Test2()
{
printf("=====Test2 starts:=====\n");
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
printf("expected result: 5.\n");
ListNode* pNode = FindKthToTail(pNode1, 1);
PrintListNode(pNode);
DestroyList(pNode1);
}
// 测试要找的结点是链表的头结点
void Test3()
{
printf("=====Test3 starts:=====\n");
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
printf("expected result: 1.\n");
ListNode* pNode = FindKthToTail(pNode1, 5);
PrintListNode(pNode);
DestroyList(pNode1);
}
// 测试空链表
void Test4()
{
printf("=====Test4 starts:=====\n");
printf("expected result: NULL.\n");
ListNode* pNode = FindKthToTail(NULL, 100);
PrintListNode(pNode);
}
// 测试输入的第二个参数大于链表的结点总数
void Test5()
{
printf("=====Test5 starts:=====\n");
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
printf("expected result: NULL.\n");
ListNode* pNode = FindKthToTail(pNode1, 6);
PrintListNode(pNode);
DestroyList(pNode1);
}
// 测试输入的第二个参数为0
void Test6()
{
printf("=====Test6 starts:=====\n");
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
printf("expected result: NULL.\n");
ListNode* pNode = FindKthToTail(pNode1, 0);
PrintListNode(pNode);
DestroyList(pNode1);
}
void main()
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
system("pause");
}