链表

目录:

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 <stack>
		
		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 <cstdio>
	#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 <cstdio>
	#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 <cstdio>
		#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 <cstdio>
			#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 <cstdio>
			#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 <cstdio>
			#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 <cstdio>
			#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 <cstdio>
			#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 <cstdio>
		#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  风御之举  阅读(40)  评论(0编辑  收藏  举报