链表双指针的应用

在一个链表里使用两个指针,可以实现一些操作
如寻找链表中倒数第K个结点,寻找中间位置结点,判断链表有没有环,以及如何找到环的入口

#include <stdio.h>
#include<stdlib.h>

typedef struct Node
{
	int Data;
	struct Node* PNext;
}Node;
typedef Node* PNode;
int CountNum;

void CreateNode(PNode* List)//创建一个链表,且赋值从0开始
{
	Node* NewNode = (Node*)malloc(sizeof(Node));
	if (!NewNode) exit(1);
	NewNode->PNext = NULL;
	NewNode->Data = CountNum++;
	(*List)->PNext = NewNode;
	*List = NewNode;
}
//寻找倒数第K个结点,第一个指针先走k步,然后第二个再走,第一个走到终点第二个指针就指向倒数第k个
int Last_But_K(PNode HNode,int k)
{
	int count = 0;
	PNode p=HNode;
	while (count < k)
	{
		count++;
		HNode = HNode->PNext;
	}
	while (HNode)
	{
		HNode = HNode->PNext;
		p = p->PNext;
	}
	return p->Data;
}
//同理一个走一步,一个走两步
int Middle(PNode HNode)
{
	PNode p = HNode;
	while (p && p->PNext)
	{
		p = p->PNext->PNext;
		HNode = HNode->PNext;
	}
	return HNode->Data;
}

//链表里面可能有环结构,利用双指针可以判断链表里面是否有环,同时可以找到环的入口

//判断有没有环,一个指针走一步,一个指针走两步,如果第一个指针到达尾部则说明没有环,如果两个指针相遇则说明有环,且有环必相遇
int If_Circle(PNode HNode)
{
	PNode p1, p2;
	p1 = p2 = HNode;
	while (1)
	{
		if (p1 && p1->PNext)p1 = p1->PNext->PNext;
		else return 0;
		p2 = p2->PNext;
		if (p1 == p2) return 1;
	}
}
//如果有环,找到环的入口,采取的方法又是一个指针走一步,另一个指针走两步,当两个指针相遇的时候
//p2比p1多走一圈,令p2再回到起点与p1都是一步一步地走,相遇处就是入口
//起点到入口的距离和相遇点到入口的距离相等
PNode Find_Entrance(PNode HNode)
{
	PNode p1, p2;
	p1 = p2 = HNode;

	do
	{
		p1 = p1->PNext->PNext;
		p2 = p2->PNext;
	} while (p1 != p2);
	p1 = HNode;
	while (p1 != p2)
	{
		p1 = p1->PNext;
		p2 = p2->PNext;
	}
	return p1;
}


int main()
{
	PNode HNode;
	HNode = (PNode)malloc(sizeof(Node));
	HNode->PNext = NULL;
	PNode List = HNode;
	for (int i = 0; i < 5; i++) CreateNode(&List);
	PNode Node1 = List;
	for (int i = 0; i < 9; i++) CreateNode(&List);
	//printf("%d\n", Last_But_K(HNode, 3));
	List->PNext = Node1;
	printf("%d\n", Middle(HNode));
	if (If_Circle(HNode))
	{
		PNode pEnce = Find_Entrance(HNode);
		printf("%d", pEnce->Data);
	}

}
posted @ 2021-03-16 22:41  empty_thought  阅读(141)  评论(0)    收藏  举报