算法实现--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;
	}
}

 

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