带环单链表及单链表的相交

一、带环单链表:     

        带环单链表的概念:当单链表的尾指针指向了链表上任一非尾结点时,即生成了一个带环单链表。

        问题一:判断是否带环(通过快慢指针实现判断,注意快指针必须是两步,慢指针必须是一步,否则可能跨过)

        问题二:求环的入口点(通过数学思想,方法是使用一指针指向开头,一指针指向环中的相交点,每次各走一步,如此所得相交点即入口点)

        问题三:约瑟夫环的决胜者问题

#include<iostream>
using namespace std;

struct Node
{
	int _data;
	Node* _next = NULL;
};

typedef Node* PList;

Node* CreateNode(int x)
{
	Node *temp = new Node;
	temp->_data = x;
	temp->_next = NULL;
	return temp;
}

void push_back(PList &head, int x)
{
	Node *tmp = head;
	if (head == NULL)
	{
		head = CreateNode(x);
	}
	else
	{
		while (tmp->_next != NULL)
			tmp = tmp->_next;
		tmp->_next = CreateNode(x);
	}
}

Node* Find(PList head, int x)
{
	Node* cur = head;
	while (cur != NULL)
	{
		if (cur->_data == x)
		{
			return cur;
		}

		cur = cur->_next;
	}
	return NULL;
}

Node* JudgeHasCircle(PList head)
{
	//运用快慢指针的思想
	Node* fast = head;
	Node* slow = head;
	Node* temp = head;

	while (fast != NULL && fast->_next != NULL)
	{
		fast = fast->_next->_next;
		slow = slow->_next;
		if (fast == slow)
			break;
	}
	if (fast != NULL)
	{
		while (temp != fast)
		{
			temp = temp->_next;
			fast = fast->_next;
		}
		return temp;
	}
	else
		return NULL;
}

//约瑟夫环游戏
Node* Joe(PList head, int k)
{
	//运用快慢指针的思想
	Node* fast = head;
	Node* slow = head;
	Node* temp = head;
	Node* dead = NULL;

	while (fast != NULL && fast->_next != NULL)
	{
		fast = fast->_next->_next;
		slow = slow->_next;
		if (fast == slow)
			break;
	}
	if (fast != NULL)
	{
		int i = k - 1;
		while (temp != temp->_next)
		{
			i = k - 1;
			while (--i > 0)
			{
				temp = temp->_next;
			}
			dead = temp->_next;
			temp->_next = temp->_next->_next;
			temp = temp->_next;
			delete dead;
			dead = NULL;
		}
		return temp;
	}
	else
		return NULL;
}

void test1()
{
	PList list1;
	list1 = NULL;
	push_back(list1, 1);
	push_back(list1, 2);
	push_back(list1, 3);
	push_back(list1, 4);
	push_back(list1, 5);
	push_back(list1, 6);
	push_back(list1, 7);
	//构建带环单链表
	Node *temp = Find(list1, 7);
	temp->_next = Find(list1, 4);
	//判断是否是带环单链表,以及返回相交结点
	temp = JudgeHasCircle(list1);
	if (temp == NULL)
		printf("无环.\n");
	else
	{
		printf("有环.\n");
		cout << temp->_data << endl;
	}
}

void test2()
{
	PList list1;
	list1 = NULL;
	push_back(list1, 1);
	push_back(list1, 2);
	push_back(list1, 3);
	push_back(list1, 4);
	push_back(list1, 5);
	push_back(list1, 6);
	push_back(list1, 7);
	//构建带环单链表
	Node *temp = Find(list1, 7);
	temp->_next = Find(list1, 1);
	Node *temp1 = Joe(list1, 2);
}

int main()
{
	PList list1;
	list1 = NULL;
	push_back(list1, 1);
	push_back(list1, 2);
	push_back(list1, 3);
	push_back(list1, 4);
	push_back(list1, 5);
	push_back(list1, 6);
	push_back(list1, 7);
	//构建无环相交的单链表
	PList list2;
	return 0;
}


二、单链表相交

        单链表相交的概念:即两条单链表存在完全重合的部分,而不是交叉某一点。

        问题1:不带环的相交

        问题2:带环的相交(注:当为带环单链表相交时,必须是两个单链表都有环,不可能存在一者有环,一者无环的情况。并且,相交之后只可能存在一个环,不可能出现多个环的情况)

        问题1的解决:(因为两者相交后,必然有一段一直到尾的部分重合,所以,可以根据尾结点判断重合)

        问题2的解决:(同上面求环是否存在的情况,通过两次判断SLst1和SList2,分别找出它们环中的一个结点,再固定其一,另一个绕环走,当出现两结点重合情况,则为相交,其它情况皆为不相交)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值