C语言:如何判断两个单向链表有相同节点?

代码如下:

/*****************************************************************
*功能:如何判断单向链表有相同节点?
*1、直观法:遍历链表1的节点和链表2的节点是否有相等
*2、找结尾相同法:判断两个链表的尾部节点是否相同
*3、构造法:将链表1的尾部指向链表2的尾部,看链表1或链表2是否存在环
*   程序员:lml    时间:2020年3月31日23:56:11 
******************************************************************/
#include <stdio.h>
#include <stdlib.h>

typedef int dt_type;

//定义链表1结构
typedef struct test{
    
    
	dt_type data;
	struct test *next;
}list,*list_p;

//开辟链表空间
list_p do_malloc()
{
    
    
	list_p L = NULL;
	if((L = (list_p)malloc(sizeof(list))) == NULL){
    
    
		printf("fail malloc-1\n");
		return NULL;
	}
	else{
    
    
		L->next = NULL;
		return L;
	}
}

//链表插入数据
int do_insert(list_p L1,list_p L2,dt_type val)
{
    
    
	list_p P = NULL;
	if((P = (list_p)malloc(sizeof(list))) == NULL){
    
    
		printf("fail malloc-2\n");
		return -1;
	}
	P->data = val;
	if(val >=0 && val < 10){
    
            //val<10时把数据插入链表1
		P->next = L1->next;
		L1->next = P;

	}
	else if(val >= 10 && val <20){
    
      //val>10 val<20时数据插入链表2
		P->next = L2->next;
		L2->next = P;
	}
	else{
    
    
		P->next = L2->next;
		L2->next = P;
	}
	if(val == 20){
    
         //当val==20的时候,让链表1接到链表2中,得到“Y”形链表
		list_p S = L1;
		while(S->next != NULL){
    
    
			S = S->next;
		}
		S->next = L2->next; //链表1链接到链表2
	}
	return 0;
}

//打印函数
void do_show(list_p L,char *tepy)
{
    
    
	list_p P=L->next;
	printf("%s:\n",tepy);
	while(P != NULL){
    
    
		printf("%d  ",P->data);
		P = P->next;
	}
	putchar(10);
}

//方法1:直观遍历法,遍历两个链表是否有相等的节点
int do_visual(list_p L1,list_p L2)
{
    
    
	list_p S1 = L1;
	list_p S2 = L2;

	while(S1->next != NULL){
    
    
		while(S2->next != NULL){
    
    
			if(S1->next == S2->next){
    
    
				printf("方法1:have same node\n");
				printf("start val:%d\n",S2->next->data);
				return 0;
			}
			S2 = S2->next;
		}
		S2 = L2; //S2重新还原,接着下次遍历
		S1 = S1->next;
	}
	printf("方法1:no same\n");
	return 0;
}

//方法2:尾部相同法,遍历两个链表尾部是否有相等的节点
int do_tailSame(list_p L1,list_p L2)
{
    
    
	list_p S1 = L1;
	list_p S2 = L2;
	list_p TEMP1 = L1;
	list_p TEMP2 = L2;
		
	while(S1->next != NULL){
    
    
		TEMP1->next = S1->next; //如果while循环退出,此时TEMP1就是尾节点地址
		S1 = S1->next;
	}
	while(S2->next != NULL){
    
    
		TEMP2->next = S2->next;	//同TEMP1	
		S2 = S2->next;
	}
	if(TEMP1->next == TEMP2->next){
    
     //比较两个尾节点是否相等
		printf("方法2:have same node!\n");
		printf("tail same memory address:%p\n",TEMP1->next);
		return 0;
	}else{
    
    
		printf("方法2:no same!\n");
	}
	return 0;
}

//方法3:尾部构造法,将链表1尾部指向链表二的头部,再判断链表二是否为环链表
int do_tailStruct(list_p L1,list_p L2)
{
    
    
	list_p S1 = L1;
	list_p S2 = L2;
	list_p TEMP1 = L1;
	list_p TEMP2 = L2;

	while(S1->next != NULL){
    
    
		S1 = S1->next;
	}
	S1->next = S2->next;
	
	while(S2->next != NULL){
    
      //运用快慢指针法判断是否为环链表
		if(S2->next == TEMP2->next){
    
     //快慢指针如果存在相同,说明是环
			printf("方法3:have same node!\n");
			return 0;
		}
		S2 = S2->next;              //指针1走一步
		TEMP2 = TEMP2->next->next;  //指针2走二步
	}
	printf("方法3:no same!\n");
	return 0;
}

//释放函数
void do_free(list_p L1,list_p L2)
{
    
    
	free(L1);
	free(L2);
}
int main(int argc, const char *argv[])
{
    
    
	//创建链表1
	list_p L1;
	if((L1 = do_malloc()) == NULL){
    
    
		printf("call malloc fail\n");
		return 0;
	}
	//创建链表2
	list_p L2;
	if((L2 = do_malloc()) == NULL){
    
    
		printf("call malloc fail\n");
		return 0;
	}
	
	//把数据插入链表,(“Y”形链表)
	int i=0;
	for(i=0;i<30;i++){
    
    
		do_insert(L1,L2,i);
	}
	
	//打印链表
	do_show(L1,"list_1");
	do_show(L2,"list_2");

	//判断是否存在相同节点,三种方法
	do_visual(L1,L2);
	do_tailSame(L1,L2);
	do_tailStruct(L1,L2);

	//释放内存
	do_free(L1,L2);
	return 0;
}

结束。

猜你喜欢

转载自blog.csdn.net/qq_19693355/article/details/105693812