交叉链表练习

版权声明:本文为博主原创文章,未经博主允许不得转载,如果有错误,欢迎指正,提前感谢。 https://blog.csdn.net/Quinlan_/article/details/86748529

https://www.bilibili.com/video/av39115738
强烈安利灯笼大神的视频...上面是视频链接…下面截图是灯笼大神视频里的…

今天学了下 怎么找交叉链表会和到一起的那个结点,做个学习笔记…
#—

这是个图...
因为不确定list1 和 list2两条链表在汇聚到某个结点之前 ,他们各自的结点数是相同的,所以要求出这个结点数的差值。长的链表的结点数 - 短的链表的结点数 == 指向长的链表的指针需要移动的结点数

如上图p1指针指向 “1”结点,p2指针指向“7”结点,通过一个求链表中结点个数的函数得到 list1的长度为6,list2结点的个数为4。6-4=2 ,这时候将p1指针向后移动2个结点。
这时候p1和p2 同步进行移动即可到达汇集的那个结点…

#include<stdio.h>
#include<stdlib.h>

//创建一个链表结点的结构体 没有什么问题
typedef struct {
    int value;
    struct Node *next;
} Node;

//这个函数是用来返回链表长度的 没有什么问题
int get_list_length(Node *list)
{
    Node *p = list;
    int length = 0;
    while( p != NULL )
    {
        ++length;
        p = (struct Node *)(p->next);
    }
    return length;
}

//移动结点用的,先看下面一个函数再看这个
Node *relocate_first_node(Node *list, int offset)
{
	//list是要移动的那个long_list  offset是往后移动的单位数
    Node *p = list;
    for(int i=0; i<offset; i++)
    {
        p = p->next;
    }
	// 移动好了.. 返回的 这个p指向的位置 呢,就是那个刚刚好的位置
    return p;
}

//这个函数用来找相同结点用的
Node *find_common_node(Node *list1, Node *list2)
{
	//先求出两条链表的长度
    int length1 = get_list_length(list1);
    int length2 = get_list_length(list2);
	
	//先假设list1比list2长
    Node *long_list = list1;
    Node *short_list = list2;
	
	//恰恰相反.jpg...
    if(  length1 < length2 )
    {
        long_list = list2;
        short_list = list1;
    }
	
	//这时候long_list指向的就是长的那条链表
	//short_list指向的就是短的那条链表
	
	//然后求一下他们差的绝对值
    int offset = abs(length1 - length2);
    
    //p1是指向长链首结点的指针,把p1往后移动offset个单位的结点
    //relocate_first_node()这个函数返回一个指针 p 
    //p1 = p    这时候p1的位置就是移动好以后的位置
    Node *p1 = relocate_first_node(long_list, offset);
    //p2的位置是首结点的位置没什么问题,因为他短
    Node *p2 = short_list;

	//这时候就可以开始一起移动了
    while( p1 != NULL )
    {
    	//当这俩指针指向同一个结点的时候
        if( p1 == p2 )
        {
        // return p1 或者p2都行
            return p1;
        }
        //p1 p2同步往后走
        //这个地方用gcc编译也出现了需要强制类型转换的地方
        //不是很懂为什么 网上没有搜到结果。。用-w给忽略了
        p1 = p1->next;
        p2 = p2->next;
    }
	// 如果是陌路人就返回NULL
    return NULL;
}

int main()
{
	//这里是构建一个上面那张图形状的交叉链表
	//虽然麻烦 但重要的还是学求结点的思想..ummm
    Node n1, n2, n3, n4, n5, n6, n7;
    n1.value = 1;
    n2.value = 2;
    n3.value = 3;
    n4.value = 4;
    n5.value = 5;
    n6.value = 6;
    n7.value = 7;
	// 这个地方灯笼大神视频里是没有(struct Node *)这个强制类型-
	//-转换的但我的编译器会给出
	//warning: assignment from incompatible pointer type
	//这个问题...所以就强制类型转换了一下...
	//后来在用gcc编译的时候 只需要加上-w 就可以忽略warning了...
    n1.next = (struct Node *)&n2;
    n2.next = (struct Node *)&n3;
    n3.next = (struct Node *)&n4;
    n4.next = (struct Node *)&n5;
    n5.next = (struct Node *)&n6;
    n6.next = NULL;
    n7.next = (struct Node *)&n4;
    
    //list1 的第一个结点是n1  list2的第一个结点是n7
    Node *list1 = &n1;
    Node *list2 = &n7;
    
    //这里验证一下这个函数是不是能用....
    printf("list1: %d\nlist2: %d\n",get_list_length(list1),
            get_list_length(list2));
    
    // find_common_node()返回的是指向结点的指针
    Node *common = find_common_node(list1, list2);
    //这时候输出值..看一下结果...就是酱
    printf("common node = %d\n", common->value);
    return 0;

}

猜你喜欢

转载自blog.csdn.net/Quinlan_/article/details/86748529