栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【数据结构】A、B为递减有序的单链表,编写函数,将它们合并成递增有序的单链表,相同元素值只保留一个结点

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【数据结构】A、B为递减有序的单链表,编写函数,将它们合并成递增有序的单链表,相同元素值只保留一个结点

文章目录
  • 1.算法思路
  • 2.定义结构体
  • 3.定义函数
    • 3.1 创建单链表
    • 3.2 合并单链表
  • 4.测试结果
  • 5.完整代码

1.算法思路
  1. 将两单链表合并,常用的方法是归并排序。每次比较两个链表的当前结点值,选择较大的结点值进行插入操作。
  2. 由于是将递减有序的链表变为递增有序的链表,那么可以考虑使用头插法,每次归并排序比较完成后将更大值的结点插入到已排序链表中,然后移动排序链表的头指针指向该结点。
2.定义结构体
typedef struct LNode {
    int data;
    struct LNode *next;
} LNode, *LinkList;

3.定义函数 3.1 创建单链表

编写函数创建单链表。输入参数为:

  • LinkList A: 单链表的头结点
  • int a[]: 该单链表的元素值
  • length: 元素值的长度
    当i < length时,循环创建结点,并使用尾插法将结点插入到当前链表的最后面,然后将链表尾指针移动至尾部,即当前结点。
void CreateList(LinkList A, int a[], int length) {
    LNode *s = (LNode *)malloc(sizeof(LNode));
    LNode *tail = A;
    s->next = NULL;
    for(int i=0; i < length; i++) {
        s = (LNode *)malloc(sizeof(LNode));//创建新结点
        s->data = a[i];
        s->next = NULL;
        tail->next = s;
        tail = tail->next;
    }
}
3.2 合并单链表
  1. 首先创建链表头结点C,它将指向已排好序的链表头结点,每次使用头插法插入新结点后都将指向此时的头结点,即新结点。
  2. 创建工作指针p,q分别指向A和B的首个数据结点。判断p,q是否为空。如果有链表为空,则返回NULL。这里假定两个链表都不为空时才进行排序,否则结束程序。
  3. 当p,q都不为空时,遍历A,B链表,比较结点值,进行如下判断:
    • p->data == q->data: 说明两结点值重复,因此选择删除一个结点,头插另一个结点。这里选择插入p结点而删除q结点。首先使用指针s只想当前结点p,然后将p结点向后移动,之后修改相应指针实现p的头插。然后将s指向q,并让q向后移动,再释放s。
    • p->data > q->data: 此时选择更大的结点即p将其插入到排序链表中,然后p后移,比较新的p和q。
    • p->data < q->data: 此时选择更大的结点即q将其插入到排序链表中,然后q后移,比较新的p和q。
  4. 当A或B遍历完成时,上述循环退出。此时判断p,q哪个指针为空。使用头插法将未空指针后面的剩余结点插入到排序链表。
LinkList MergeList(LinkList A, LinkList B) {
    //C用于指向以合并链表的头结点
    LinkList C = (LinkList)malloc(sizeof(LNode));
    C->next = NULL;
    //p,q用于遍历两个链表,s用于指向当前结点更大的结点
    LNode *p = A->next, *q = B->next, *s = NULL;
    if(!p || !q) {
        printf("链表为空!n");
        return NULL;
    }
    while(p && q) {//p,q都不为空,开始比较
        if(p->data == q->data) {//p,q相等,删除一个结点
            //首先将一个结点头插到当前链表中
            s = p;
            p = p->next;
            s->next = C->next;
            C->next = s;
            //删除另一个结点
            s = q;
            q = q->next;
            free(s);
        }
        else {
            if(p->data > q->data) {//p的结点值更大,将s移到p
                s = p;
                p = p->next;
            } else{//q的结点值更大,将s移到q
                s = q;
                q = q->next;
            }
            s->next = C->next;
            C->next = s;
        }
    }
    while(p) {//当q为空时,将q剩下的进行头插法
        s = p;
        p = p->next;
        s->next = C->next;
        C->next = s;
    }
    while(q) {//当p为空时,将p剩下的进行头插法
        s = q;
        q = q->next;
        s->next = C->next;
        C->next = s;
    }
    return C->next;
}
4.测试结果

给出两组测试结果:

LinkList A = (LinkList)malloc(sizeof(LNode));
    LinkList B = (LinkList)malloc(sizeof(LNode));
    int a[] = {7,6,5,4,3,2,1};
    int b[] = {9,5,3,1};
    CreateList(A, a, sizeof(a) / sizeof(a[0]));
    CreateList(B, b, sizeof(b) / sizeof(b[0]));

LinkList A = (LinkList)malloc(sizeof(LNode));
    LinkList B = (LinkList)malloc(sizeof(LNode));
    int a[] = {7,5,3,1};
    int b[] = {7,5,3,1};
    CreateList(A, a, sizeof(a) / sizeof(a[0]));
    CreateList(B, b, sizeof(b) / sizeof(b[0]));

5.完整代码
#include 
using namespace std;

//定义结构体
typedef struct LNode {
    int data;
    struct LNode *next;
} LNode, *LinkList;

//合并两个递减链表并实现递增有序
LinkList MergeList(LinkList A, LinkList B) {
    //C用于指向以合并链表的头结点
    LinkList C = (LinkList)malloc(sizeof(LNode));
    C->next = NULL;
    //p,q用于遍历两个链表,s用于指向当前结点更大的结点
    LNode *p = A->next, *q = B->next, *s = NULL;
    if(!p || !q) {
        printf("链表为空!n");
        return NULL;
    }
    while(p && q) {//p,q都不为空,开始比较
        if(p->data == q->data) {//p,q相等,删除一个结点
            //首先将一个结点头插到当前链表中
            s = p;
            p = p->next;
            s->next = C->next;
            C->next = s;
            //删除另一个结点
            s = q;
            q = q->next;
            free(s);
        }
        else {
            if(p->data > q->data) {//p的结点值更大,将s移到p
                s = p;
                p = p->next;
            } else{//q的结点值更大,将s移到q
                s = q;
                q = q->next;
            }
            s->next = C->next;
            C->next = s;
        }
    }
    while(p) {//当q为空时,将q剩下的进行头插法
        s = p;
        p = p->next;
        s->next = C->next;
        C->next = s;
    }
    while(q) {//当p为空时,将p剩下的进行头插法
        s = q;
        q = q->next;
        s->next = C->next;
        C->next = s;
    }
    return C->next;
}

//创建单链表
void CreateList(LinkList A, int a[], int length) {
    LNode *s = (LNode *)malloc(sizeof(LNode));
    LNode *tail = A;
    s->next = NULL;
    for(int i=0; i < length; i++) {
        s = (LNode *)malloc(sizeof(LNode));//创建新结点
        s->data = a[i];
        s->next = NULL;
        tail->next = s;
        tail = tail->next;
    }
}

int main() {
    //创建单链表
    LinkList A = (LinkList)malloc(sizeof(LNode));
    LinkList B = (LinkList)malloc(sizeof(LNode));
    int a[] = {7,6,5,4,3,2,1};
    int b[] = {9,5,3,1};
    CreateList(A, a, sizeof(a) / sizeof(a[0]));
    CreateList(B, b, sizeof(b) / sizeof(b[0]));
    LinkList p = A->next;
    //打印查看原始数据
    printf("A链表的数据为:n");
    while(p) {
        printf("%dt", p->data);
        p = p->next;
    }
    printf("n");
    p = B->next;
    printf("B链表的数据为:n");
    while(p) {
        printf("%dt", p->data);
        p = p->next;
    }
    printf("n");
    //获取合并后的链表
    LinkList q = MergeList(A, B);
    //打印输出
    printf("修改后链表的数据为:n");
    while(q) {
        printf("%dt", q->data);
        q = q->next;
    }
    return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1019465.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号