ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

合并两个有序单链表

2021-09-12 13:02:11  阅读:203  来源: 互联网

标签:结点 单链 指向 合并 LinkList 有序 节点 pNext 指针


我们考虑如何将两个值域有序的单链表合并成一个新的有序单链表,使用原有的单链表的头结点作为新链表的头结点。

我们可以通过不断比较两个表的数据域的大小,先将较小者插入到以原有表的其中一个头结点构造的空表尾部,再比较再将较小者插入新表的尾部,一直执行下去。当遇到原有两个表其中一个表,现到达尾节点时,只需将没有到达尾节点的表剩余的节点全部插入到新表尾部即可。

下面我们代码实现(注意看代码注释)

void combine_linklist(LinkList Ll1, LinkList Ll2)
{   
    LinkList C; //指向空表C的头结点的指针(后续构造的新表)
    LinkList p = Ll1->pNext; //指针p始终指向表一中将要判断指针域大小的节点,初始指向表一头结点的后驱节点
    LinkList q = Ll2->pNext; //指针q始终指向表二中将要判断指针域大小的节点,初始指向表二头结点的后驱节点
    LinkList r; //指针r始终指向空表C的尾节点,初始指向空表C的头结点
    LinkList s; //临时保存指针p或q,可以通过直接操作s,来操作未进行后移的指针p或q

    
    //借助第一个链表的头结点构造一个新的空表,该空表用来存储新合并的有序链表
    C = Ll1;    
    C->pNext = NULL;
    
    //指针r,始终指向空表C的尾节点。(初始指向空表C的头结点)
    r = C;

    //释放表二的头结点
    free(Ll2);  
    
    //当p和q都不为空的时候执行循环,当其中有一个为空时,只需将不为空所在的表剩余的节点全部插入到表C尾部即可
    while (p && q)  
    {   
        //整个if语句是用来找到,表一和表二中将要比较数据域的两个节点中较小的节点,并将指向该节点的指针用s临时保存
        //如果表一的数据域小于表二的数据域
        if (p->data < q->data)
        {
            //先将指针p保存到指针s, 因为后续p要后移,以保证可以通过直接操作s,来操作未进行后移的指针p
            s = p;

            //p后移,以保证始终指向表一中将要判断指针域大小的节点
            p = p->pNext;  
        }
        //如果表二的数据域小于或等于表一的数据域
        else 
        {   
            //先将指针q保存到指针s, 因为后续q要后移,以保证可以通过直接操作s,来操作未进行后移的指针q
            s = q;

            //q后移,以保证始终指向表二中将要判断指针域大小的节点
            q = q->pNext;
        }  
        
        //将找到的较小者,通过操作临时保存过指向该较小者的指针s,来插入表C的尾部
        s->pNext = r->pNext; //相当于将插入表C尾部的节点的指针域置空 
        r->pNext = s; //将表C的尾节点的指针域指向要插入的节点(执行插入操作)
        r = r->pNext; //r后移,以保证始终指向表C的尾节点
    } 
    
    //判断循环是因为p空而结束,还是因为q空而结束
    if (p)
        //如果是q空导致,则将表一剩余部分插入到C表的尾部  
        r->pNext = p;   
    else
        //如果p空导致,则将表二剩余部分插入到C表的尾部   
        r->pNext = q; 

    //结束函数
    return;
}

因为上述代码只是整个可以运行的代码中独立封装的一个函数,不太完整,下面给出完整函数(完整函数中去除了这个合并函数) 

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

typedef struct Node
{
    int data; //数据域
    struct Node * pNext; //指针域
}LNode, * LinkList;

//函数声明
LinkList create_linklist(); //创建一个链表
void combine_linklist(LinkList, LinkList); //合并两个有序表
void show_linklist(LinkList); //输出链表数据域


int main(void)
{
    LinkList Ll1 = NULL; //定义一个指向空的节点指针
    LinkList Ll2 = NULL; //定义一个指向空的节点指针
    
    Ll1 = create_linklist(); //创建第一个单链表
    Ll2 = create_linklist(); //创建第二个单链表

    show_linklist(Ll1); //输出表一
    show_linklist(Ll2); //输出表二

    combine_linklist(Ll1, Ll2); //合并表一表二

    show_linklist(Ll1); //输出合并的新表

    return 0;
}

LinkList create_linklist()
{
    int len; //用来存储节点的个数
    int i; //for循环中的循环变量
    int val; //用来存放节点的值域


    //为头结点分配内存
    LinkList Ll = (LinkList)malloc(sizeof(LNode));
    Ll->pNext = NULL;
    
    //判断是否分配成功
    if(!Ll)
    {
        printf("动态内存分配失败,程序退出!\n");
        exit(-1);
    }

    //请求用户输入节点个数
    printf("请输入节点的个数:\n");
    scanf("%d", &len);

    //定义一个始终指向当前链表尾节点的指针,初始指向头结点
    LinkList pTail = Ll;
    pTail->pNext = NULL;

    for (i = 0; i < len; i++)
    {
        //每循环一次生成一个新的节点
        LinkList LNew = (LinkList)malloc(sizeof(LNode));

        //判断是否分配成功
        if(!LNew)
        {
            printf("动态内存分配失败,程序退出!\n");
            exit(-1);
        }

        //请求用户输入新节点的值
        printf("请输入第%d个节点的值\n", i+1);
        scanf("%d", &val);

        //将用户输入的值存储到数据域
        LNew->data = val;

        //将原始链表的最后一个节点挂在新节点上
        pTail->pNext = LNew;

        //新节点变成当前的尾节点,需要将其指针域变为空
        LNew->pNext = NULL;

        //pTail后移,使其指向当前的尾节点
        pTail = LNew;
    }

    //提示用户链表创建成功
    printf("链表创建成功!\n");

    //返回指向头结点的指针
    return Ll;   
}

void show_linklist(LinkList Ll)
{
    LinkList p = Ll->pNext;

    while(p != NULL)
    {
        printf("%d ", p->data);
        p = p->pNext;
    }

    printf("\n");

    return;
}

标签:结点,单链,指向,合并,LinkList,有序,节点,pNext,指针
来源: https://blog.csdn.net/yuki_1209/article/details/120243807

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有