判断两个单链表是否相交,若相交并找出相交的第一个点

链表的正确相交情况如下:

 判断两个链表是否相交

//确定两个单链表是否相交 (用两个指针跑到两个单链表的尾结点,然后判断是否是同一个尾结点)
bool Intersect(PNode plist1, PNode plist2)
{
	//assert
	PNode p1 = plist1;
	PNode p2 = plist2;

	for(p1; p1->next!=NULL; p1=p1->next);   //此时for循环结束  p1在plist1这个单链表的尾结点上
	for(p2; p2->next!=NULL; p2=p2->next);   //此时for循环结束  p2在plist2这个单链表的尾结点上

	return p1 == p2;
}

 

判断两个链表是否相交并求出相交点 

//确定两个单链表是否相交,并且相交的话,返回第一个相交点
struct Node *Intersect_get_Node(PNode plist1, PNode plist2)
{
	//assert
	int len1 = Get_length(plist1);
	int len2 = Get_length(plist2);

	//接下来 我们需要保证  让p永远指向较长的单链表
	PNode p = len1>=len2 ? plist1 : plist2;
	PNode q = len1>=len2 ? plist2 : plist1;

	for(int i=0; i<abs(len1-len2); i++)//abs 计算绝对值  
	{
		p = p->next;
	}

	//此时,p已经将差值跑完  这个时候 只需要循环判断p和q是否是用一个节点即可

	while(p != q)//这里要么p和q指向有效地址 退出循环    要么p==q==NULL 退出循环
	{
		p = p->next;
		q = q->next;
	}


	return p; //return q;
}

测试: 

int main()
{
	Node head1;
	Init_list(&head1);
	for (int i = 0; i < 10; i++)
	{
		Insert_pos(&head1, i, i + 1);
	}

	Node head2;
	Init_list(&head2);
	for (int i = 0; i < 20; i++)
	{
		Insert_pos(&head2, i, i + 101);
	}
	Show(&head1);
	Show(&head2);
	bool tag1 = Intersect(&head1, &head2);
	if (tag1)
	{
		printf("相交了\n");
	}
	else
	{
		printf("没有相交\n");
	}

	PNode p = &head2;
	for (int i = 0; i < 12; i++)
	{
		p = p->next;//p最后指向plist2的  112
	}
	PNode q = &head1;
	for (int i = 0; i < 5; i++)
	{
		q = q->next;//q最后指向plist1的  5
	}

	p->next = q->next;//手动发生相交
	Show(&head1);
	Show(&head2);
	//1 2 3 4 5 6 7 8 9 10
	//101 102 103 104 105 106 107 108 109 110 111 112 6 7 8 9 10

	tag1 = Intersect(&head1, &head2);
	if (tag1)
	{
		printf("相交了\n");
	}
	else
	{
		printf("没有相交\n");
	}


	struct Node* tmp = Intersect_get_Node(&head1, &head2);
	if (tmp != NULL)
	{
		printf("相交点的有效值为:%d\n", tmp->data);
	}

	bool tag2 = Del_Node((&head1)->next);
	if (tag2)
	{
		Show(&head1);
	}

	return 0;
}

 

#include <stdio.h> #include <stdlib.h> //定义链表结构体 struct Node { int data; struct Node *next; }; //创建链表函数 struct Node *createList(int n) { struct Node *head, *p, *q; int i, num; head = (struct Node *)malloc(sizeof(struct Node)); head->next = NULL; q = head; for (i = 0; i < n; i++) { printf("请输入第%d个节的值:", i + 1); scanf("%d", &num); p = (struct Node *)malloc(sizeof(struct Node)); p->data = num; p->next = NULL; q->next = p; q = p; } return head; } //输出链表函数 void printList(struct Node *head) { struct Node *p; p = head->next; while (p != NULL) { printf("%d ", p->data); p = p->next; } printf("\n"); } //逆置链表函数 void reverseList(struct Node *head) { struct Node *p, *q, *r; p = head->next; q = NULL; while (p != NULL) { r = p->next; p->next = q; q = p; p = r; } head->next = q; } //找中间节函数 struct Node *findMiddleNode(struct Node *head) { struct Node *p, *q; p = head->next; q = head->next; while (q != NULL && q->next != NULL) { p = p->next; q = q->next->next; } return p; } //找倒数第k个节函数 struct Node *findKthNode(struct Node *head, int k) { struct Node *p, *q; p = head->next; q = head->next; while (k > 0 && q != NULL) { q = q->next; k--; } if (k > 0) return NULL; while (q != NULL) { p = p->next; q = q->next; } return p; } //删除倒数第k个节函数 void deleteKthNode(struct Node *head, int k) { struct Node *p, *q; p = head; q = head->next; while (k > 0 && q != NULL) { p = q; q = q->next; k--; } if (k > 0) return; p->next = q->next; free(q); } //判断链表是否有环函数 int hasCycle(struct Node *head) { struct Node *p, *q; p = head; q = head; while (q != NULL && q->next != NULL) { p = p->next; q = q->next->next; if (p == q) return 1; } return 0; } //找出环的交点函数 struct Node *findCycleNode(struct Node *head) { struct Node *p, *q; int flag = 0; p = head; q = head; while (q != NULL && q->next != NULL) { p = p->next; q = q->next->next; if (p == q) { flag = 1; break; } } if (flag == 0) return NULL; p = head; while (p != q) { p = p->next; q = q->next; } return p; } //判断两个单链表是否相交函数 int isIntersect(struct Node *head1, struct Node *head2) { struct Node *p, *q; p = head1; q = head2; while (p->next != NULL) { p = p->next; } while (q->next != NULL) { q = q->next; } if (p == q) return 1; else return 0; } int main() { struct Node *head1, *head2, *p; int n, k; printf("请输入链表1的节个数:"); scanf("%d", &n); head1 = createList(n); printf("链表1为:"); printList(head1); reverseList(head1); printf("逆置后的链表1为:"); printList(head1); p = findMiddleNode(head1); printf("链表1的中间节为:%d\n", p->data); printf("请输入链表1的倒数第k个节:"); scanf("%d", &k); p = findKthNode(head1, k); printf("链表1的倒数第%d个节为:%d\n", k, p->data); deleteKthNode(head1, k); printf("删除倒数第%d个节后的链表1为:", k); printList(head1); if (hasCycle(head1)) { p = findCycleNode(head1); printf("链表1有环,环的交点为:%d\n", p->data); } else { printf("链表1没有环\n"); } printf("请输入链表2的节个数:"); scanf("%d", &n); head2 = createList(n); printf("链表2为:"); printList(head2); if (isIntersect(head1, head2)) { printf("链表1和链表2相交\n"); p = findCycleNode(head1); printf("链表1和链表2的交点为:%d\n", p->data); } else { printf("链表1和链表2不相交\n"); } return 0; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值