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