链表所有的相关操作(合并,查找,逆制,判环,相交)

1.合并两个有序链表,合并以后的链表依旧有序。

#pragma once
typedef struct ListNode
{
	int _data;
	ListNode* _next;

}Node;

void Display(Node* head)     //非递归打印
{
	while (head)
	{
		cout << head->_data << " ";
		head = head->_next;
	}
	cout << endl;
}

Node* MeageList(Node* l1, Node* l2) //合并链表
{
	Node* NewNode = new Node;
	Node* cur1;
	Node* cur2;
	if (NULL == l1)
	{
		return l2;
	}

	if (NULL == l2)
	{
		return l1;
	}

	if (l1->_data < l2->_data)    //吧头数据小的一个作为新链表的头
	{
		NewNode->_data = l1->_data;
		cur1 = l1->_next;
		cur2 = l2;
	}
	else
	{
		NewNode->_data = l2->_data;
		cur2 = l2->_next;
		cur1 = l1;
	}

	Node* NewList = NewNode;
	while (cur1 && cur2)            //把剩余链表连接在后面
	{
		if (cur1->_data > cur2->_data)
		{
			NewNode->_next = cur2;
			NewNode = NewNode->_next;
			cur2 = cur2->_next;
		}
		else
		{
			NewNode->_next = cur1;
			NewNode = NewNode->_next;
			cur1 = cur1->_next;
		}
	}
	if (cur1 == NULL)
	{
		NewNode->_next = cur2;
	}
	else
		NewNode->_next = cur1;

	return NewList;
}


Node* MeageListRe(Node* l1, Node* l2) // 递归合并
{
	if (NULL == l1)
	{
		return l2;
	}

	if (NULL == l2)
	{
		return l1;
	}

	if (l1->_data < l2->_data)
	{
		l1->_next = MeageListRe(l1->_next, l2);
		return l1;
	}
	else
	{
		l2->_next = MeageListRe(l2->_next, l1);
		return l2;
	}
}

2. 逆置/反转单链表,查找单链表的倒数第k个节点,要求只能遍历一次链表 。

typedef struct ListNode       //链表节点
{
	int _data;
	ListNode* _next;
}Node;



Node* ReverceList(Node* list)    //逆制单链表   (取下一个节点,头插) 
{
	if (NULL == list)
	{
		return NULL;
	}
	Node* Head = list->_next;  

	Node* NewHead = list; //原链表的头节点,变成新链表的尾节点。
	Node* cur = list->_next;
	NewHead->_next = NULL;

	while (cur)
	{
		Head = cur;
		cur = cur->_next;
		Head->_next = NewHead;  //找到下一个节点,插在前面
		NewHead = Head;
	}
	return Head;
}

Node* ReFind(Node* list, int k)  //查找倒数第K个节点, (两指针 相差K-1步)
{
	if (NULL == list)
	{
		return NULL;
	}
	Node* ptr1 = list;
	Node* ptr2 = list;

	while (k--)
	{
		ptr1 = ptr1->_next;    //ptr1先走 k-1 步
	}

	while (ptr1&&ptr2)  
	{
		ptr1 = ptr1->_next;
		ptr2 = ptr2->_next;
	}
	return ptr2;
}

3. 判断链表是否带环?若带环求环的长度?若带环求环的入口点?

typedef struct ListNode    //链表节点
{
	int _data;
	ListNode* _next;
}Node;



Node* Find(Node* list, int key)  //查找某个节点
{
	if (NULL == list)
		return NULL;

	Node* node = list;
	while (node)
	{
		if (node->_data == key)
		{
			return node;
		}
		node = node->_next;
	}
	return NULL;
}

Node* MakeRing(Node* list)      // 构建带环链表
{
	Node* ret = Find(list, 9);

	Node* newnode = list;
	Node* newhead = list;
	while (newnode->_next)
	{
		newnode = newnode->_next;
	}
	newnode->_next = ret;

	return newhead;
}

bool JudgeRing(Node* list)     //判断链表是否带环
{
	if (NULL == list)
		return false;

	Node* fast = list;
	Node* slow = list;
	while (fast && fast->_next)
	{
		fast = fast->_next->_next;
		slow = slow->_next;

		if (slow == fast)
			return true;
	}
	return false;
}

Node* FindRingnode(Node* list)     //找链表环的入口点
{
	if (NULL == list)
		return NULL;

	Node* fast = list;
	Node* slow = list;
	while (fast && fast->_next)
	{
		fast = fast->_next->_next;
		slow = slow->_next;

		if (slow == fast)
			break;
	}

	if (fast && fast->_next)
	{
		slow = list;
	}
	else
		return NULL;
	// 若带环 ,slow从头开始走,fast从相遇点开始走,第一次相遇即为交点
	while (slow != fast)
	{
		slow = slow->_next;
		fast = fast->_next;
	}
	return slow;
}

int RingLong(Node* list)             //求环的长度
{
	Node* node = FindRingnode(list); //找到还的入口点
	int count = 0;
	Node* node1 = node;
	while (node)
	{
		node = node->_next;
		count++;
		if (node == node1)  //当在环内走一圈,走的距离就是环长
			break;
	}
	return count;
}


4. 判断两个链表是否相交,若相交,求交点。(假设链表不带环)。判断两个链表是否相交,若相交,求交点。(假设链表可能带环)

typedef struct ListNode
{
	int _data;
	ListNode* _next;
}Node;



Node* Find(Node* list, int key)  //查找结点
{
	assert(list);
	Node* node = list;
	while (node)
	{
		if (node->_data == key)
		{
			return node;
		}
		node = node->_next;
	}
	return NULL;
}

Node* MakeRing(Node* list)       //建造带环链表
{
	assert(list);
	Node* node = list;
	while (node->_next)
	{
		node = node->_next;
	}
	node->_next = Find(list, 1);
	return list;

}

void MakeCrossList(Node* list1, Node* list2)      //建造相交链表
{
	assert(list1);
	assert(list2);

	Node* node2 = list2;
	while (node2->_next)
	{
		node2 = node2->_next;
	}
	node2->_next = Find(list1, 3);

}

bool JudgeRing(Node* list)     //判断链表是否带环
{
	if (NULL == list)
		return false;

	Node* fast = list;
	Node* slow = list;
	while (fast && fast->_next)  //快慢指针是否相遇
	{
		fast = fast->_next->_next;
		slow = slow->_next;

		if (slow == fast)
			return true;
	}
	return false;
}

Node* FindRingnode(Node* list)     //找带环链表的入口点
{
	if (NULL == list)
		return NULL;

	Node* fast = list;
	Node* slow = list;
	while (fast && fast->_next)
	{
		fast = fast->_next->_next;
		slow = slow->_next;

		if (slow == fast)
			break;
	}

	if (fast && fast->_next)
	{
		slow = list;
	}
	else
		return NULL;

	// 若带环 ,slow从头开始走,fast从相遇点开始走,第一次相遇即为交点
	while (slow != fast)
	{
		slow = slow->_next;
		fast = fast->_next;
	}
	return slow;
}

int RingLong(Node* list)             //求环的长度
{
	Node* node = FindRingnode(list);
	int count = 0;
	Node* node1 = node;
	while (node)
	{
		node = node->_next;
		count++;
		if (node == node1)
			break;
	}
	return count;
}

Node* JudgeCross1(Node* list1, Node* list2)   //不带环相交的判断
{
	assert(list1);
	assert(list2);

	Node* head1 = list1;
	Node* head2 = list2;
	while (head2->_next)
	{
		head2 = head2->_next;
	}
	head2->_next = head1;      //让 list1 的头链上 list2 的结尾

	//判断新链表是否带环
	//若新链表带环,则环的入口点就是第一个相交的点

	return FindRingnode(list2);
}

int GetListlength(Node* list)     //求链表长度
{
	assert(list);
	Node* head = list;
	int len = 0;
	while (head)
	{
		if (JudgeRing(list))      //带环链表的长
		{
			Node* node = FindRingnode(list);
			while (node != head)
			{
				head = head->_next;
				len++;
			}
			len = len + RingLong(list);  //链表长 = 头结点到环入口的长度 + 环的长度
			break;
		}
		else      //不带环链表的长
		{
			len++;
			head = head->_next;
		}
	}
	return len;
}
Node* JudgeCross2(Node* list1, Node* list2)  //链表带环相交
{
	//1.环外相交
	//2.环内相交
	assert(list1);
	assert(list2);
	int long1 = GetListlength(list1);
	int long2 = GetListlength(list2);
	int step = 0;
	Node* head1 = list1;
	Node* head2 = list2;

	if (long1 > long2)     //长的链表先走,让链表等长
	{
		step = long1 - long2;
		while (step--)
			head1 = head1->_next;
	}
	else
	{
		step = long2 - long1;
		while (step--)
			head2 = head2->_next;
	}

	if (JudgeRing(list1) && JudgeRing(list2)) //若相交,两条链表必然都带环
	{
		while (FindRingnode(list1) != head2)
		{
			head2 = head2->_next;
		}

		if (head2 == FindRingnode(list1))  //若相交,list1 环上的点(入口点),必在 list2 上
		{
			while (head1 != FindRingnode(list1))  //1.环外相交 
			{
				head1 = head1->_next;
				head2 = head2->_next;
				if (head1 == head2)
					return head1;
			}
			if (head1 == FindRingnode(list1))  //2.环上相交(环有两个入口点),环的任意一个入口点就是交点
				return FindRingnode(list1);
		}
		else
			return NULL;
	}
	return NULL;
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值