链表

目录:

6、【剑指Offer学习】【面试题06:从尾到头打印链表】

18、【剑指Offer学习】【面试题18:在O(1)时间删除链表结点】

22、【剑指Offer学习】【面试题22:链表中倒数第k个结点】

23、【剑指Offer学习】【面试题23:链表中环的入口结点】

24、【剑指Offer学习】【面试题24:反转链表】

25、【剑指Offer学习】【面试题25:合并两个排序的链表】

35、【剑指Offer学习】【面试题35:复杂链表的复制】

36、【剑指Offer学习】【面试题36:二叉搜索树与双向链表】

52、【剑指Offer学习】【面试题52:两个链表的第一个公共结点】

6. 【剑指Offer学习】【面试题06:从尾到头打印链表】

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题6:从尾到头打印链表
// 题目:输入一个链表的头结点,从尾到头反过来打印出每个结点的值。

include "..\Utilities\List.h"

include

void PrintListReversingly_Iteratively(ListNode* pHead)
{
std::stack<ListNode*> nodes;

ListNode* pNode = pHead;
while(pNode != nullptr)
{
nodes.push(pNode);
pNode = pNode->m_pNext;
}

while(!nodes.empty())
{
pNode = nodes.top();
printf("%d\t", pNode->m_nValue);
nodes.pop();
}
}

void PrintListReversingly_Recursively(ListNode* pHead)
{
if(pHead != nullptr)
{
if (pHead->m_pNext != nullptr)
{
PrintListReversingly_Recursively(pHead->m_pNext);
}

printf("%d\t", pHead->m_nValue);
}
}

// 测试代码
void Test(ListNode* pHead)
{
PrintList(pHead);
PrintListReversingly_Iteratively(pHead);
printf("\n");
PrintListReversingly_Recursively(pHead);
}

// 1->2->3->4->5
void Test1()
{
printf("\nTest1 begins.\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);

Test(pNode1);

DestroyList(pNode1);
}

// 只有一个结点的链表: 1
void Test2()
{
printf("\nTest2 begins.\n");

ListNode* pNode1 = CreateListNode(1);

Test(pNode1);

DestroyList(pNode1);
}

// 空链表
void Test3()
{
printf("\nTest3 begins.\n");

Test(nullptr);
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();

return 0;
}

18. 面试题18:在O(1)时间删除链表结点

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题18(一):在O(1)时间删除链表结点
// 题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该
// 结点。

include

include "..\Utilities\List.h"

void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted)
{
if(!pListHead || !pToBeDeleted)
return;

// 要删除的结点不是尾结点
if(pToBeDeleted->m_pNext != nullptr)
{
ListNode* pNext = pToBeDeleted->m_pNext;
pToBeDeleted->m_nValue = pNext->m_nValue;
pToBeDeleted->m_pNext = pNext->m_pNext;

delete pNext;
pNext = nullptr;
}
// 链表只有一个结点,删除头结点(也是尾结点)
else if(*pListHead == pToBeDeleted)
{
delete pToBeDeleted;
pToBeDeleted = nullptr;
pListHead = nullptr;
}
// 链表中有多个结点,删除尾结点
else
{
ListNode
pNode = *pListHead;
while(pNode->m_pNext != pToBeDeleted)
{
pNode = pNode->m_pNext;
}

pNode->m_pNext = nullptr;
delete pToBeDeleted;
pToBeDeleted = nullptr;
}
}

// 测试代码
void Test(ListNode* pListHead, ListNode* pNode)
{
printf("The original list is: \n");
PrintList(pListHead);

printf("The node to be deleted is: \n");
PrintListNode(pNode);

DeleteNode(&pListHead, pNode);

printf("The result list is: \n");
PrintList(pListHead);
}

// 链表中有多个结点,删除中间的结点
void Test1()
{
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);

Test(pNode1, pNode3);

DestroyList(pNode1);
}

// 链表中有多个结点,删除尾结点
void Test2()
{
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);

Test(pNode1, pNode5);

DestroyList(pNode1);
}

// 链表中有多个结点,删除头结点
void Test3()
{
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);

Test(pNode1, pNode1);

DestroyList(pNode1);
}

// 链表中只有一个结点,删除头结点
void Test4()
{
ListNode* pNode1 = CreateListNode(1);

Test(pNode1, pNode1);
}

// 链表为空
void Test5()
{
Test(nullptr, nullptr);
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();

return 0;
}


/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题18(二):删除链表中重复的结点
// 题目:在一个排序的链表中,如何删除重复的结点?例如,在图3.4(a)中重复
// 结点被删除之后,链表如图3.4(b)所示。

include

include "../Utilities/list.h"

void DeleteDuplication(ListNode** pHead)
{
if(pHead == nullptr || *pHead == nullptr)
return;

ListNode* pPreNode = nullptr;
ListNode* pNode = *pHead;
while(pNode != nullptr)
{
ListNode *pNext = pNode->m_pNext;
bool needDelete = false;
if(pNext != nullptr && pNext->m_nValue == pNode->m_nValue)
needDelete = true;

if(!needDelete)
{
pPreNode = pNode;
pNode = pNode->m_pNext;
}
else
{
int value = pNode->m_nValue;
ListNode* pToBeDel = pNode;
while(pToBeDel != nullptr && pToBeDel->m_nValue == value)
{
pNext = pToBeDel->m_pNext;

delete pToBeDel;
pToBeDel = nullptr;

pToBeDel = pNext;
}

if(pPreNode == nullptr)
*pHead = pNext;
else
pPreNode->m_pNext = pNext;
pNode = pNext;
}
}
}

// 测试代码
void Test(char* testName, ListNode** pHead, int* expectedValues, int expectedLength)
{
if(testName != nullptr)
printf("%s begins: ", testName);

DeleteDuplication(pHead);

int index = 0;
ListNode* pNode = *pHead;
while(pNode != nullptr && index < expectedLength)
{
if(pNode->m_nValue != expectedValues[index])
break;

pNode = pNode->m_pNext;
index++;
}

if(pNode == nullptr && index == expectedLength)
printf("Passed.\n");
else
printf("FAILED.\n");
}

// 某些结点是重复的
void Test1()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(3);
ListNode* pNode5 = CreateListNode(4);
ListNode* pNode6 = CreateListNode(4);
ListNode* pNode7 = CreateListNode(5);

ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
ConnectListNodes(pNode5, pNode6);
ConnectListNodes(pNode6, pNode7);

ListNode* pHead = pNode1;

int expectedValues[] = { 1, 2, 5 };
Test("Test1", &pHead, expectedValues, sizeof(expectedValues) / sizeof(int));

DestroyList(pHead);
}

// 没有重复的结点
void Test2()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ListNode* pNode6 = CreateListNode(6);
ListNode* pNode7 = CreateListNode(7);

ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
ConnectListNodes(pNode5, pNode6);
ConnectListNodes(pNode6, pNode7);

ListNode* pHead = pNode1;

int expectedValues[] = { 1, 2, 3, 4, 5, 6, 7 };
Test("Test2", &pHead, expectedValues, sizeof(expectedValues) / sizeof(int));

DestroyList(pHead);
}

// 除了一个结点之外其他所有结点的值都相同
void Test3()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(1);
ListNode* pNode3 = CreateListNode(1);
ListNode* pNode4 = CreateListNode(1);
ListNode* pNode5 = CreateListNode(1);
ListNode* pNode6 = CreateListNode(1);
ListNode* pNode7 = CreateListNode(2);

ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
ConnectListNodes(pNode5, pNode6);
ConnectListNodes(pNode6, pNode7);

ListNode* pHead = pNode1;

int expectedValues[] = { 2 };
Test("Test3", &pHead, expectedValues, sizeof(expectedValues) / sizeof(int));

DestroyList(pHead);
}

// 所有结点的值都相同
void Test4()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(1);
ListNode* pNode3 = CreateListNode(1);
ListNode* pNode4 = CreateListNode(1);
ListNode* pNode5 = CreateListNode(1);
ListNode* pNode6 = CreateListNode(1);
ListNode* pNode7 = CreateListNode(1);

ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
ConnectListNodes(pNode5, pNode6);
ConnectListNodes(pNode6, pNode7);

ListNode* pHead = pNode1;

Test("Test4", &pHead, nullptr, 0);

DestroyList(pHead);
}

// 所有结点都成对出现
void Test5()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(1);
ListNode* pNode3 = CreateListNode(2);
ListNode* pNode4 = CreateListNode(2);
ListNode* pNode5 = CreateListNode(3);
ListNode* pNode6 = CreateListNode(3);
ListNode* pNode7 = CreateListNode(4);
ListNode* pNode8 = CreateListNode(4);

ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
ConnectListNodes(pNode5, pNode6);
ConnectListNodes(pNode6, pNode7);
ConnectListNodes(pNode7, pNode8);

ListNode* pHead = pNode1;

Test("Test5", &pHead, nullptr, 0);

DestroyList(pHead);
}

// 除了两个结点之外其他结点都成对出现
void Test6()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(1);
ListNode* pNode3 = CreateListNode(2);
ListNode* pNode4 = CreateListNode(3);
ListNode* pNode5 = CreateListNode(3);
ListNode* pNode6 = CreateListNode(4);
ListNode* pNode7 = CreateListNode(5);
ListNode* pNode8 = CreateListNode(5);

ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
ConnectListNodes(pNode5, pNode6);
ConnectListNodes(pNode6, pNode7);
ConnectListNodes(pNode7, pNode8);

ListNode* pHead = pNode1;

int expectedValues[] = { 2, 4 };
Test("Test6", &pHead, expectedValues, sizeof(expectedValues) / sizeof(int));

DestroyList(pHead);
}

// 链表中只有两个不重复的结点
void Test7()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);

ConnectListNodes(pNode1, pNode2);

ListNode* pHead = pNode1;

int expectedValues[] = { 1, 2 };
Test("Test7", &pHead, expectedValues, sizeof(expectedValues) / sizeof(int));

DestroyList(pHead);
}

// 结点中只有一个结点
void Test8()
{
ListNode* pNode1 = CreateListNode(1);

ConnectListNodes(pNode1, nullptr);

ListNode* pHead = pNode1;

int expectedValues[] = { 1 };
Test("Test8", &pHead, expectedValues, sizeof(expectedValues) / sizeof(int));

DestroyList(pHead);
}

// 结点中只有两个重复的结点
void Test9()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(1);

ConnectListNodes(pNode1, pNode2);

ListNode* pHead = pNode1;

Test("Test9", &pHead, nullptr, 0);

DestroyList(pHead);
}

// 空链表
void Test10()
{
ListNode* pHead = nullptr;

Test("Test10", &pHead, nullptr, 0);
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
Test7();
Test8();
Test9();
Test10();

return 0;
}

22. 面试题22:链表中倒数第k个结点

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

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

include

include "..\Utilities\List.h"

ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
{
if(pListHead == nullptr || k == 0)
return nullptr;

ListNode *pAhead = pListHead;
ListNode *pBehind = nullptr;

for(unsigned int i = 0; i < k - 1; ++ i)
{
if(pAhead->m_pNext != nullptr)
pAhead = pAhead->m_pNext;
else
{
return nullptr;
}
}

pBehind = pListHead;
while(pAhead->m_pNext != nullptr)
{
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: nullptr.\n");
ListNode* pNode = FindKthToTail(nullptr, 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: nullptr.\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: nullptr.\n");
ListNode* pNode = FindKthToTail(pNode1, 0);
PrintListNode(pNode);

DestroyList(pNode1);
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();

return 0;
}

23. 面试题23:链表中环的入口结点

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题23:链表中环的入口结点
// 题目:一个链表中包含环,如何找出环的入口结点?例如,在图3.8的链表中,
// 环的入口结点是结点3。

include

include "../Utilities/list.h"

ListNode* MeetingNode(ListNode* pHead)
{
if(pHead == nullptr)
return nullptr;

ListNode* pSlow = pHead->m_pNext;
if(pSlow == nullptr)
return nullptr;

ListNode* pFast = pSlow->m_pNext;
while(pFast != nullptr && pSlow != nullptr)
{
if(pFast == pSlow)
return pFast;

pSlow = pSlow->m_pNext;

pFast = pFast->m_pNext;
if(pFast != nullptr)
pFast = pFast->m_pNext;
}

return nullptr;
}

ListNode* EntryNodeOfLoop(ListNode* pHead)
{
ListNode* meetingNode = MeetingNode(pHead);
if(meetingNode == nullptr)
return nullptr;

// 得到环中结点的数目
int nodesInLoop = 1;
ListNode* pNode1 = meetingNode;
while(pNode1->m_pNext != meetingNode)
{
pNode1 = pNode1->m_pNext;
++nodesInLoop;
}

// 先移动pNode1,次数为环中结点的数目
pNode1 = pHead;
for(int i = 0; i < nodesInLoop; ++i)
pNode1 = pNode1->m_pNext;

// 再移动pNode1和pNode2
ListNode* pNode2 = pHead;
while(pNode1 != pNode2)
{
pNode1 = pNode1->m_pNext;
pNode2 = pNode2->m_pNext;
}

return pNode1;
}

// ==================== Test Code ====================
void Test(char* testName, ListNode* pHead, ListNode* entryNode)
{
if(testName != nullptr)
printf("%s begins: ", testName);

if(EntryNodeOfLoop(pHead) == entryNode)
printf("Passed.\n");
else
printf("FAILED.\n");
}

// A list has a node, without a loop
void Test1()
{
ListNode* pNode1 = CreateListNode(1);

Test("Test1", pNode1, nullptr);

DestroyList(pNode1);
}

// A list has a node, with a loop
void Test2()
{
ListNode* pNode1 = CreateListNode(1);
ConnectListNodes(pNode1, pNode1);

Test("Test2", pNode1, pNode1);

delete pNode1;
pNode1 = nullptr;
}

// A list has multiple nodes, with a loop
void Test3()
{
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);
ConnectListNodes(pNode5, pNode3);

Test("Test3", pNode1, pNode3);

delete pNode1;
pNode1 = nullptr;
delete pNode2;
pNode2 = nullptr;
delete pNode3;
pNode3 = nullptr;
delete pNode4;
pNode4 = nullptr;
delete pNode5;
pNode5 = nullptr;
}

// A list has multiple nodes, with a loop
void Test4()
{
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);
ConnectListNodes(pNode5, pNode1);

Test("Test4", pNode1, pNode1);

delete pNode1;
pNode1 = nullptr;
delete pNode2;
pNode2 = nullptr;
delete pNode3;
pNode3 = nullptr;
delete pNode4;
pNode4 = nullptr;
delete pNode5;
pNode5 = nullptr;
}

// A list has multiple nodes, with a loop
void Test5()
{
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);
ConnectListNodes(pNode5, pNode5);

Test("Test5", pNode1, pNode5);

delete pNode1;
pNode1 = nullptr;
delete pNode2;
pNode2 = nullptr;
delete pNode3;
pNode3 = nullptr;
delete pNode4;
pNode4 = nullptr;
delete pNode5;
pNode5 = nullptr;
}

// A list has multiple nodes, without a loop
void Test6()
{
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);

Test("Test6", pNode1, nullptr);

DestroyList(pNode1);
}

// Empty list
void Test7()
{
Test("Test7", nullptr, nullptr);
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
Test7();

return 0;
}

24. 面试题24:反转链表

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题24:反转链表
// 题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的
// 头结点。

include

include "..\Utilities\List.h"

ListNode* ReverseList(ListNode* pHead)
{
ListNode* pReversedHead = nullptr;
ListNode* pNode = pHead;
ListNode* pPrev = nullptr;
while(pNode != nullptr)
{
ListNode* pNext = pNode->m_pNext;

if(pNext == nullptr)
pReversedHead = pNode;

pNode->m_pNext = pPrev;

pPrev = pNode;
pNode = pNext;
}

return pReversedHead;
}

// 测试代码
ListNode* Test(ListNode* pHead)
{
printf("The original list is: \n");
PrintList(pHead);

ListNode* pReversedHead = ReverseList(pHead);

printf("The reversed list is: \n");
PrintList(pReversedHead);

return pReversedHead;
}

// 输入的链表有多个结点
void Test1()
{
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);

ListNode* pReversedHead = Test(pNode1);

DestroyList(pReversedHead);
}

// 输入的链表只有一个结点
void Test2()
{
ListNode* pNode1 = CreateListNode(1);

ListNode* pReversedHead = Test(pNode1);

DestroyList(pReversedHead);
}

// 输入空链表
void Test3()
{
Test(nullptr);
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();

return 0;
}

25. 面试题25:合并两个排序的链表

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题25:合并两个排序的链表
// 题目:输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按
// 照递增排序的。例如输入图3.11中的链表1和链表2,则合并之后的升序链表如链
// 表3所示。

include

include "..\Utilities\List.h"

ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(pHead1 == nullptr)
return pHead2;
else if(pHead2 == nullptr)
return pHead1;

ListNode* pMergedHead = nullptr;

if(pHead1->m_nValue < pHead2->m_nValue)
{
pMergedHead = pHead1;
pMergedHead->m_pNext = Merge(pHead1->m_pNext, pHead2);
}
else
{
pMergedHead = pHead2;
pMergedHead->m_pNext = Merge(pHead1, pHead2->m_pNext);
}

return pMergedHead;
}

// 测试代码
ListNode* Test(char* testName, ListNode* pHead1, ListNode* pHead2)
{
if(testName != nullptr)
printf("%s begins:\n", testName);

printf("The first list is:\n");
PrintList(pHead1);

printf("The second list is:\n");
PrintList(pHead2);

printf("The merged list is:\n");
ListNode* pMergedHead = Merge(pHead1, pHead2);
PrintList(pMergedHead);

printf("\n\n");

return pMergedHead;
}

// list1: 1->3->5
// list2: 2->4->6
void Test1()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode5 = CreateListNode(5);

ConnectListNodes(pNode1, pNode3);
ConnectListNodes(pNode3, pNode5);

ListNode* pNode2 = CreateListNode(2);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode6 = CreateListNode(6);

ConnectListNodes(pNode2, pNode4);
ConnectListNodes(pNode4, pNode6);

ListNode* pMergedHead = Test("Test1", pNode1, pNode2);

DestroyList(pMergedHead);
}

// 两个链表中有重复的数字
// list1: 1->3->5
// list2: 1->3->5
void Test2()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode5 = CreateListNode(5);

ConnectListNodes(pNode1, pNode3);
ConnectListNodes(pNode3, pNode5);

ListNode* pNode2 = CreateListNode(1);
ListNode* pNode4 = CreateListNode(3);
ListNode* pNode6 = CreateListNode(5);

ConnectListNodes(pNode2, pNode4);
ConnectListNodes(pNode4, pNode6);

ListNode* pMergedHead = Test("Test2", pNode1, pNode2);

DestroyList(pMergedHead);
}

// 两个链表都只有一个数字
// list1: 1
// list2: 2
void Test3()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);

ListNode* pMergedHead = Test("Test3", pNode1, pNode2);

DestroyList(pMergedHead);
}

// 一个链表为空链表
// list1: 1->3->5
// list2: 空链表
void Test4()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode5 = CreateListNode(5);

ConnectListNodes(pNode1, pNode3);
ConnectListNodes(pNode3, pNode5);

ListNode* pMergedHead = Test("Test4", pNode1, nullptr);

DestroyList(pMergedHead);
}

// 两个链表都为空链表
// list1: 空链表
// list2: 空链表
void Test5()
{
ListNode* pMergedHead = Test("Test5", nullptr, nullptr);
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();

return 0;
}

35. 面试题35:复杂链表的复制

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题35:复杂链表的复制
// 题目:请实现函数ComplexListNode* Clone(ComplexListNode* pHead),复
// 制一个复杂链表。在复杂链表中,每个结点除了有一个m_pNext指针指向下一个
// 结点外,还有一个m_pSibling 指向链表中的任意结点或者nullptr。

include

include "ComplexList.h"

void CloneNodes(ComplexListNode* pHead);
void ConnectSiblingNodes(ComplexListNode* pHead);
ComplexListNode* ReconnectNodes(ComplexListNode* pHead);

ComplexListNode* Clone(ComplexListNode* pHead)
{
CloneNodes(pHead);
ConnectSiblingNodes(pHead);
return ReconnectNodes(pHead);
}

void CloneNodes(ComplexListNode* pHead)
{
ComplexListNode* pNode = pHead;
while(pNode != nullptr)
{
ComplexListNode* pCloned = new ComplexListNode();
pCloned->m_nValue = pNode->m_nValue;
pCloned->m_pNext = pNode->m_pNext;
pCloned->m_pSibling = nullptr;

pNode->m_pNext = pCloned;

pNode = pCloned->m_pNext;
}
}

void ConnectSiblingNodes(ComplexListNode* pHead)
{
ComplexListNode* pNode = pHead;
while(pNode != nullptr)
{
ComplexListNode* pCloned = pNode->m_pNext;
if(pNode->m_pSibling != nullptr)
{
pCloned->m_pSibling = pNode->m_pSibling->m_pNext;
}

pNode = pCloned->m_pNext;
}
}

ComplexListNode* ReconnectNodes(ComplexListNode* pHead)
{
ComplexListNode* pNode = pHead;
ComplexListNode* pClonedHead = nullptr;
ComplexListNode* pClonedNode = nullptr;

if(pNode != nullptr)
{
pClonedHead = pClonedNode = pNode->m_pNext;
pNode->m_pNext = pClonedNode->m_pNext;
pNode = pNode->m_pNext;
}

while(pNode != nullptr)
{
pClonedNode->m_pNext = pNode->m_pNext;
pClonedNode = pClonedNode->m_pNext;

pNode->m_pNext = pClonedNode->m_pNext;
pNode = pNode->m_pNext;
}

return pClonedHead;
}

// 测试代码
void Test(const char* testName, ComplexListNode* pHead)
{
if(testName != nullptr)
printf("%s begins:\n", testName);

printf("The original list is:\n");
PrintList(pHead);

ComplexListNode* pClonedHead = Clone(pHead);

printf("The cloned list is:\n");
PrintList(pClonedHead);
}

// -----------------
// |/ |
// 1-------2-------3-------4-------5
// | | /|\ /|
// --------+-------- |
// -------------------------
void Test1()
{
ComplexListNode* pNode1 = CreateNode(1);
ComplexListNode* pNode2 = CreateNode(2);
ComplexListNode* pNode3 = CreateNode(3);
ComplexListNode* pNode4 = CreateNode(4);
ComplexListNode* pNode5 = CreateNode(5);

BuildNodes(pNode1, pNode2, pNode3);
BuildNodes(pNode2, pNode3, pNode5);
BuildNodes(pNode3, pNode4, nullptr);
BuildNodes(pNode4, pNode5, pNode2);

Test("Test1", pNode1);
}

// m_pSibling指向结点自身
// -----------------
// |/ |
// 1-------2-------3-------4-------5
// | | /|\ /|
// | | -- |
// |------------------------|
void Test2()
{
ComplexListNode* pNode1 = CreateNode(1);
ComplexListNode* pNode2 = CreateNode(2);
ComplexListNode* pNode3 = CreateNode(3);
ComplexListNode* pNode4 = CreateNode(4);
ComplexListNode* pNode5 = CreateNode(5);

BuildNodes(pNode1, pNode2, nullptr);
BuildNodes(pNode2, pNode3, pNode5);
BuildNodes(pNode3, pNode4, pNode3);
BuildNodes(pNode4, pNode5, pNode2);

Test("Test2", pNode1);
}

// m_pSibling形成环
// -----------------
// |/ |
// 1-------2-------3-------4-------5
// | /|
// | |
// |---------------|
void Test3()
{
ComplexListNode* pNode1 = CreateNode(1);
ComplexListNode* pNode2 = CreateNode(2);
ComplexListNode* pNode3 = CreateNode(3);
ComplexListNode* pNode4 = CreateNode(4);
ComplexListNode* pNode5 = CreateNode(5);

BuildNodes(pNode1, pNode2, nullptr);
BuildNodes(pNode2, pNode3, pNode4);
BuildNodes(pNode3, pNode4, nullptr);
BuildNodes(pNode4, pNode5, pNode2);

Test("Test3", pNode1);
}

// 只有一个结点
void Test4()
{
ComplexListNode* pNode1 = CreateNode(1);
BuildNodes(pNode1, nullptr, pNode1);

Test("Test4", pNode1);
}

// 鲁棒性测试
void Test5()
{
Test("Test5", nullptr);
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();

return 0;
}

36. 面试题36:二叉搜索树与双向链表

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题36:二叉搜索树与双向链表
// 题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求
// 不能创建任何新的结点,只能调整树中结点指针的指向。

include

include "..\Utilities\BinaryTree.h"

void ConvertNode(BinaryTreeNode* pNode, BinaryTreeNode** pLastNodeInList);

BinaryTreeNode* Convert(BinaryTreeNode* pRootOfTree)
{
BinaryTreeNode *pLastNodeInList = nullptr;
ConvertNode(pRootOfTree, &pLastNodeInList);

// pLastNodeInList指向双向链表的尾结点,
// 我们需要返回头结点
BinaryTreeNode *pHeadOfList = pLastNodeInList;
while(pHeadOfList != nullptr && pHeadOfList->m_pLeft != nullptr)
pHeadOfList = pHeadOfList->m_pLeft;

return pHeadOfList;
}

void ConvertNode(BinaryTreeNode* pNode, BinaryTreeNode** pLastNodeInList)
{
if(pNode == nullptr)
return;

BinaryTreeNode *pCurrent = pNode;

if (pCurrent->m_pLeft != nullptr)
ConvertNode(pCurrent->m_pLeft, pLastNodeInList);

pCurrent->m_pLeft = pLastNodeInList;
if(
pLastNodeInList != nullptr)
(*pLastNodeInList)->m_pRight = pCurrent;

*pLastNodeInList = pCurrent;

if (pCurrent->m_pRight != nullptr)
ConvertNode(pCurrent->m_pRight, pLastNodeInList);
}

// 测试代码
void PrintDoubleLinkedList(BinaryTreeNode* pHeadOfList)
{
BinaryTreeNode* pNode = pHeadOfList;

printf("The nodes from left to right are:\n");
while(pNode != nullptr)
{
printf("%d\t", pNode->m_nValue);

if(pNode->m_pRight == nullptr)
break;
pNode = pNode->m_pRight;
}

printf("\nThe nodes from right to left are:\n");
while(pNode != nullptr)
{
printf("%d\t", pNode->m_nValue);

if(pNode->m_pLeft == nullptr)
break;
pNode = pNode->m_pLeft;
}

printf("\n");
}

void DestroyList(BinaryTreeNode* pHeadOfList)
{
BinaryTreeNode* pNode = pHeadOfList;
while(pNode != nullptr)
{
BinaryTreeNode* pNext = pNode->m_pRight;

delete pNode;
pNode = pNext;
}
}

void Test(char* testName, BinaryTreeNode* pRootOfTree)
{
if(testName != nullptr)
printf("%s begins:\n", testName);

PrintTree(pRootOfTree);

BinaryTreeNode* pHeadOfList = Convert(pRootOfTree);

PrintDoubleLinkedList(pHeadOfList);
}

// 10
// /
// 6 14
// /\ /
// 4 8 12 16
void Test1()
{
BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10);
BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6);
BinaryTreeNode* pNode14 = CreateBinaryTreeNode(14);
BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8);
BinaryTreeNode* pNode12 = CreateBinaryTreeNode(12);
BinaryTreeNode* pNode16 = CreateBinaryTreeNode(16);

ConnectTreeNodes(pNode10, pNode6, pNode14);
ConnectTreeNodes(pNode6, pNode4, pNode8);
ConnectTreeNodes(pNode14, pNode12, pNode16);

Test("Test1", pNode10);

DestroyList(pNode4);
}

// 5
// /
// 4
// /
// 3
// /
// 2
// /
// 1
void Test2()
{
BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3);
BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2);
BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1);

ConnectTreeNodes(pNode5, pNode4, nullptr);
ConnectTreeNodes(pNode4, pNode3, nullptr);
ConnectTreeNodes(pNode3, pNode2, nullptr);
ConnectTreeNodes(pNode2, pNode1, nullptr);

Test("Test2", pNode5);

DestroyList(pNode1);
}

// 1
//
// 2
//
// 3
//
// 4
//
// 5
void Test3()
{
BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1);
BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2);
BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3);
BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);

ConnectTreeNodes(pNode1, nullptr, pNode2);
ConnectTreeNodes(pNode2, nullptr, pNode3);
ConnectTreeNodes(pNode3, nullptr, pNode4);
ConnectTreeNodes(pNode4, nullptr, pNode5);

Test("Test3", pNode1);

DestroyList(pNode1);
}

// 树中只有1个结点
void Test4()
{
BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1);
Test("Test4", pNode1);

DestroyList(pNode1);
}

// 树中没有结点
void Test5()
{
Test("Test5", nullptr);
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();

return 0;
}

52. 面试题52:两个链表的第一个公共结点

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题52:两个链表的第一个公共结点
// 题目:输入两个链表,找出它们的第一个公共结点。

include

include "..\Utilities\List.h"

unsigned int GetListLength(ListNode* pHead);

ListNode* FindFirstCommonNode(ListNode *pHead1, ListNode *pHead2)
{
// 得到两个链表的长度
unsigned int nLength1 = GetListLength(pHead1);
unsigned int nLength2 = GetListLength(pHead2);
int nLengthDif = nLength1 - nLength2;

ListNode* pListHeadLong = pHead1;
ListNode* pListHeadShort = pHead2;
if(nLength2 > nLength1)
{
pListHeadLong = pHead2;
pListHeadShort = pHead1;
nLengthDif = nLength2 - nLength1;
}

// 先在长链表上走几步,再同时在两个链表上遍历
for(int i = 0; i < nLengthDif; ++i)
pListHeadLong = pListHeadLong->m_pNext;

while((pListHeadLong != nullptr) &&
(pListHeadShort != nullptr) &&
(pListHeadLong != pListHeadShort))
{
pListHeadLong = pListHeadLong->m_pNext;
pListHeadShort = pListHeadShort->m_pNext;
}

// 得到第一个公共结点
ListNode* pFisrtCommonNode = pListHeadLong;

return pFisrtCommonNode;
}

unsigned int GetListLength(ListNode* pHead)
{
unsigned int nLength = 0;
ListNode* pNode = pHead;
while(pNode != nullptr)
{
++nLength;
pNode = pNode->m_pNext;
}

return nLength;
}

// 测试代码
void DestroyNode(ListNode* pNode);

void Test(char* testName, ListNode* pHead1, ListNode* pHead2, ListNode* pExpected)
{
if(testName != nullptr)
printf("%s begins: ", testName);

ListNode* pResult = FindFirstCommonNode(pHead1, pHead2);
if(pResult == pExpected)
printf("Passed.\n");
else
printf("Failed.\n");
}

// 第一个公共结点在链表中间
// 1 - 2 - 3
// 6 - 7
// 4 - 5 /
void Test1()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ListNode* pNode6 = CreateListNode(6);
ListNode* pNode7 = CreateListNode(7);

ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode6);
ConnectListNodes(pNode4, pNode5);
ConnectListNodes(pNode5, pNode6);
ConnectListNodes(pNode6, pNode7);

Test("Test1", pNode1, pNode4, pNode6);

DestroyNode(pNode1);
DestroyNode(pNode2);
DestroyNode(pNode3);
DestroyNode(pNode4);
DestroyNode(pNode5);
DestroyNode(pNode6);
DestroyNode(pNode7);
}

// 没有公共结点
// 1 - 2 - 3 - 4
//
// 5 - 6 - 7
void Test2()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ListNode* pNode6 = CreateListNode(6);
ListNode* pNode7 = CreateListNode(7);

ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode5, pNode6);
ConnectListNodes(pNode6, pNode7);

Test("Test2", pNode1, pNode5, nullptr);

DestroyList(pNode1);
DestroyList(pNode5);
}

// 公共结点是最后一个结点
// 1 - 2 - 3 - 4
// 7
// 5 - 6 /
void Test3()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ListNode* pNode6 = CreateListNode(6);
ListNode* pNode7 = CreateListNode(7);

ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode7);
ConnectListNodes(pNode5, pNode6);
ConnectListNodes(pNode6, pNode7);

Test("Test3", pNode1, pNode5, pNode7);

DestroyNode(pNode1);
DestroyNode(pNode2);
DestroyNode(pNode3);
DestroyNode(pNode4);
DestroyNode(pNode5);
DestroyNode(pNode6);
DestroyNode(pNode7);
}

// 公共结点是第一个结点
// 1 - 2 - 3 - 4 - 5
// 两个链表完全重合
void Test4()
{
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);

Test("Test4", pNode1, pNode1, pNode1);

DestroyList(pNode1);
}

// 输入的两个链表有一个空链表
void Test5()
{
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);

Test("Test5", nullptr, pNode1, nullptr);

DestroyList(pNode1);
}

// 输入的两个链表有一个空链表
void Test6()
{
Test("Test6", nullptr, nullptr, nullptr);
}

void DestroyNode(ListNode* pNode)
{
delete pNode;
pNode = nullptr;
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();

return 0;
}

posted @ 2019-12-11 19:49  风御之举  阅读(117)  评论(0)    收藏  举报