问题:有两个链表,如何判断是否相交,若相交,找出相交的起始节点
一、介绍
链表相交:
若两个链表相交,则两个链表有共同的节点,那从这个节点之后,后面的节点都会重叠,知道链表结束。若相交,则两个链表呈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");
}