算法實現--list相關

#pragma once
#include <vector>
#include <string>
#include <iostream>

using namespace std;

namespace List
{
	struct ListNode {
		int val;
		ListNode* next;
		ListNode(int x) : val(x), next(NULL) {}
		
	};

	// 打印鏈表
	void PrintList(ListNode* phead, string strFun = "list")
	{
		printf("%s: ", strFun.c_str());
		if (phead == nullptr)
		{
			printf("is empty.");
		}
		printf("%d, ", phead->val);

		ListNode* pCur = phead->next;
		while (pCur != nullptr)
		{
			printf("%d, ", pCur->val);
			pCur = pCur->next;
		}
		printf("\n");
	}

	// 創建鏈表
	ListNode* CreateList(const vector<int>& v)
	{
		ListNode* pHead = nullptr;
		if (v.empty())
		{
			return pHead;
		}

		pHead = new ListNode(v[0]);
		if (pHead == nullptr)
		{
			return pHead;
		}

		ListNode* pPre = pHead;
		for (int i = 1; i < v.size(); ++i)
		{
			ListNode* pNew = new ListNode(v[i]);
			if (pNew != nullptr)
			{
				pPre->next = pNew;
				pPre = pNew;
			}
		}

		// 同時打印鏈表
		PrintList(pHead, __FUNCTION__);

		return pHead;
	}

	// 反轉鏈表
	// 雙指針實現
	ListNode* ReverseList1(ListNode* pHead)
	{
		ListNode* pCur = nullptr;
		ListNode* pNext = pHead;
		while (pNext != nullptr)
		{
			ListNode* pTemp = pNext->next;
			pNext->next = pCur;
			pCur = pNext;
			pNext = pTemp;
		}

		pHead = pCur;

		// 同時打印鏈表
		PrintList(pHead, __FUNCTION__);

		return pHead;
	}

	// 反轉鏈表
	// 遞歸實現,首先通過遞歸確定尾端結點,並進行翻轉操作,返回代表着我已經將你下一個結點以後的結點都翻轉好了,你只需要翻轉你和你的下一個結點。
	ListNode* ReverseList2(ListNode* pHead)
	{
		if (pHead == nullptr || pHead->next == nullptr)
			return pHead;
		
		// 一直遞歸到尾結點pRet返回
		ListNode* pRet = ReverseList2(pHead->next);
		pHead->next->next = pHead;
		pHead->next = nullptr;

		return pRet;
	}

	// 分割鏈表,
	// 編寫程序以 x 爲基準分割鏈表,使得所有小於 x 的節點排在大於或等於 x 的節點之前。
	// 可以只交互節點中的數值
	ListNode* PartitionList(ListNode* pHead, int x)
	{
		ListNode* p1 = pHead;
		ListNode* p2 = pHead;

		while (p2 != nullptr)
		{
			if (p2->val < x)
			{
				// 交換
				int temp = p1->val;
				p1->val = p2->val;
				p2->val = temp;

				p1 = p1->next;
			}
			p2 = p2->next;
		}

		// 同時打印鏈表
		PrintList(pHead, __FUNCTION__);

		return pHead;
	}

	// 判斷兩鏈表相交
	// 思想:存在A、B兩個鏈表,其中交點爲p,兩鏈表相交長度爲c,A鏈表中p點前的長度爲a,B鏈表中p點前的長度爲b,需要滿足走過的路程 a+c+b = b+c+a,則會相遇
	// 創建兩個指針 pA 和 pB,分別初始化爲鏈表 A 和 B 的頭結點。然後讓它們向後逐結點遍歷。
	// 當 pA到達鏈表的尾部時,將它重定位到鏈表 B 的頭結點(你沒看錯,就是鏈表 B); 類似的,當 pB 到達鏈表的尾部時,將它重定位到鏈表 A 的頭結點。
	// 若在某一時刻 pA 和 pB 相遇,則 pA/ pB 爲相交結點,此時pA路程爲a+c+b, pB的路程爲b+c+a
	// 即使兩個鏈表沒有相交點,事實上,仍然可以統一處理,因爲這種情況意味着相交點就是null
	ListNode* GetIntersectionNode(ListNode *pHeadA, ListNode *pHeadB) 
	{
		ListNode* pA = pHeadA;
		ListNode* pB = pHeadB;
		while (pA != pB)
		{
			pA = pA == nullptr ? pHeadB : pA->next;
			pB = pB == nullptr ? pHeadA : pB->next;
		}
		
		// 打印
		if (pA == nullptr)
		{
			printf("%s: no", __FUNCTION__);
		}
		else
		{
			printf("%s: %d", __FUNCTION__, pA->val);
		}

		return pA;
	}

	// 判斷鏈表成環
	// 快慢雙指針實現
	bool HasCycle(ListNode *pHead) 
	{
		if (pHead == nullptr || pHead->next == nullptr)
			return false;

		ListNode *p1 = pHead;
		ListNode *p2 = pHead->next;
		while (p1 != p2)
		{
			if (p2 == nullptr || p2->next == nullptr)
			{
				return false;
			}
			p2 = p2->next->next;
			p1 = p1->next;
		}

		return true;
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章