(面试题)数据结构:链表相交

文章讲述了如何使用栈来判断两个链表是否相交,以及如果相交,如何找到相交节点的方法,通过创建两个栈分别存储链表元素,利用栈顶元素判断相交,再通过循环出栈找到相交节点的位置。
摘要由CSDN通过智能技术生成

问题:有两个链表,如何判断是否相交,若相交,找出相交的起始节点

一、介绍

链表相交:

若两个链表相交,则两个链表有共同的节点,那从这个节点之后,后面的节点都会重叠,知道链表结束。若相交,则两个链表呈Y形。

二、解法

1.暴力解:

分别遍历两条链表,观察是否有相同的节点。 在遍历第一条链表的同时也遍历第二条链表,第一次找到相同的节点即位第一个交点,若第一条链表遍历完之后,未找到相同的节点,则不存在交点

2.栈:(更推荐)

创建两个栈,将两个链表分别存入两个栈中,入栈结束后,只需通过top栈顶指针的值判断是否相同即可判断两个链表是否相交。栈顶元素相同,则两链表相交。若相交,则让两个栈循环出栈,直到遇到两个出栈的节点不相同,则这个节点的后一个节点就是一个相交的节点。

三、代码

例:

1.申明链表和栈的结构体

#ifndef __LINK_LIST_H__
#define __LINK_LIST_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 7

//链表的结构体
typedef struct link_list{
	union{
		int data;
		int len;
	};
	struct link_list *next;
}link_list,*list_p;

//桟的结构体
typedef struct seq_stack{
	int data[MAX];
	int top;
}seq_stack,*seq_p;

//创建头节点
list_p creat_head();
//创建节点
list_p creat_node(int data);
//头插
void insert_head(list_p H,int data);
//尾插
void insert_tail(list_p H,int data);
//遍历输出
void out_put(list_p H);


//创建顺序桟
seq_p creat_stack();
//判空
int empty_stack(seq_p S);
//判满
int full_stack(seq_p S);
//入桟
void push_stack(seq_p S,int data);
//出桟
int pop_stack(seq_p S);


#endif

2.链表的创建头节点、创建节点、头插、尾插、遍历输出

#include "link_list.h"

//创建头节点
list_p creat_head(){
	list_p H=(list_p)malloc(sizeof(link_list));
	if(H==NULL){
		printf("空间申请失败\n");
		return NULL;
	}
	H->next=NULL;
	H->len=0;
	return H;
}
//创建节点
list_p creat_node(int data){
	list_p new=(list_p)malloc(sizeof(link_list));
	if(new==NULL){
		printf("空间申请失败\n");
		return NULL;
	}
	new->data=data;
	return new;
}
//头插
void insert_head(list_p H,int data){
	if(H==NULL){
		printf("空间申请失败\n");
		return;
	}
	list_p new=creat_node(data);
	new->next=H->next;
	H->next=new;
	H->len++;

}
//尾插
void insert_tail(list_p H,int data){
	if(H==NULL){
		printf("空间申请失败\n");
		return;
	}
	list_p p=H;
	while(p->next!=NULL){
		p=p->next;
	}
	list_p new=creat_node(data);
	new->next=p->next;
	p->next=new;
	H->len++;

}
//遍历输出
void out_put(list_p H){
	if(H==NULL){
		printf("空间申请失败\n");
		return;
	}
	list_p p=H->next;
	while(p!=NULL){
		printf("%d ",p->data);
		p=p->next;
	}
	putchar(10);
}

3.栈的创建顺序栈、判空、判满、入栈、出栈

//创建顺序桟
seq_p creat_stack(){
	seq_p S=(seq_p)malloc(sizeof(seq_stack));
	if(S==NULL){
		printf("空间申请失败\n");
		return NULL;
	}
	S->top=-1;
	return S;
}
//判空
int empty_stack(seq_p S){
	if(S==NULL){
		printf("空间申请失败\n");
		return -1;
	}
	return S->top==-1?1:0;

}
//判满
int full_stack(seq_p S){
	if(S==NULL){
		printf("空间申请失败\n");
		return -1;
	}
	return S->top==MAX?1:0;
}
//入桟
void push_stack(seq_p S,int data){
	if(S==NULL){
		printf("空间申请失败\n");
		return;
	}
	if(full_stack(S)){
		printf("桟满,不能插入\n");
		return;
	}
	S->top++;
	S->data[S->top]=data;
}
//出桟
int pop_stack(seq_p S){
	if(S==NULL){
		printf("空间申请失败\n");
		return -1;
	}
	if(empty_stack(S)){
		printf("桟空\n");
		return 0;
	}
	return S->data[S->top];
}

4.main函数

#include "link_list.h"
int main(){
	list_p H1=creat_head();
	list_p H2=creat_head();
	seq_p S1=creat_stack();
	seq_p S2=creat_stack();
	insert_tail(H1,1);
	insert_tail(H1,3);
	insert_tail(H1,5);
	insert_tail(H1,8);
	insert_tail(H1,10);
	insert_tail(H2,2);
	insert_tail(H2,4);
	insert_tail(H2,6);
	insert_tail(H2,8);
	insert_tail(H2,10);
	printf("链表1为: ");
	out_put(H1);
	printf("链表2为: ");
	out_put(H2);
	list_p p1=H1->next;
	list_p p2=H2->next;

	//将两链表的值传入两个桟中
	while(p1!=NULL){
		push_stack(S1,p1->data);
		p1=p1->next;
	}
	while(p2!=NULL){
		push_stack(S2,p2->data);
		p2=p2->next;
	}
	//判断两个桟的桟顶元素是否相等
	if(S1->data[S1->top]==S2->data[S2->top]){
		printf("两链表相交\n");
		//判断出相交了之后,让两桟循环出桟,找到一个不相同的元素
		//这个元素的后一个元素就是第一次相交的节点
		while(empty_stack(S1)!=1 && empty_stack(S2)!=1){
			if(pop_stack(S1)!=pop_stack(S2)){
				printf("相交的节点为%d\n",S1->top+1);
				break;
			}
			S1->top--;
			S2->top--;
		}
	}
	else
		printf("两链表不相交\n");


}

四、效果演示 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值