算法——有序表的合并

算法——有序表的合并

概念解释:

有序集合:集合中元素按值非递减排列。

问题描述:

现在有有两个有序结合A和B,要求一个新的有序集合C=AUB,且使集合C中的元素任然按照值非递减。

eg :A={1,3,5,7,9} B={2,4,6,8} C={1,2,3,4,5,6,7,8,9}

分析:

先确定C集合的长度与内存为A和B长度和,内存和。

然后就是讨论插入问题,先把C设置为空表,然后对集合A和B中元素进行比较,把比较小的元素插入C中。为了方便A与B中元素的比较我们需要工具指针分别指向A与B的元素,来进行标记,若设pa指向当前的元素为pa,pb指向的元素为pb,那么C表中插入的c元素所要插入的值便是pa与pb中的较小者(等于的话也插入结果一样)
c = { a ( a < = b ) b ( a > b ) c=\left\{ \begin{matrix} a (a<=b) \\ b (a>b) \end{matrix} \right. c={a(a<=b)b(a>b)
插入之后,较小的那个数的指针向后移动。

代码实现

顺序表实现

  1. 先确定C链表的长度,申请所需空间

  2. 然后创建三个工具指针分别指向三个表的首元素。

  3. 然后再创建a,b的尾指针方便判断停止条件 (当指a,b初指针有一个指向尾指针的时候就可以结束,把那个未能到结束的直接插入C表就可以了)

#include "iostream"
struct SqlList{
    int *data;
    int length;
};
void MergeList_Sq(SqlList LA, SqlList LB, SqlList &LC){
    LC.length=LA.length+LB.length;
    LC.data=new int[LC.length];
    int *pa=LA.data;
    int *pb=LB.data;
    int *pc=LC.data;
    int *pa_last=LA.data+LA.length-1;
    int *pb_last=LB.data+LB.length-1;
    while ((pa<=pa_last) && (pb<=pb_last)){
        if(*pa<=*pb) *pc++=*pa++;
        else *pc++=*pb++;
//   if(*pa<=*pb) *pc++=*pa++;
//        else *pc++=*pb++;
//这代码都写的啥啊,根本看不懂,给解释一下,下面是上面代码的展开形式
//        if (*pa <= *pb) {
//            *pc = *pa;
//            pa++;
//        } else {
//            *pc = *pb;
//            pb++;
//        }
//        pc++;

    }
    while(pa<=pa_last) *pc++=*pa++;
    while(pb<=pb_last) *pc++=*pb++;
}
int main() {
    SqlList LA, LB, LC;

    // 初始化LA和LB
    LA.length = 5;
    LA.data = new int[LA.length];
    LA.data[0] = 1;
    LA.data[1] = 3;
    LA.data[2] = 5;
    LA.data[3] = 7;
    LA.data[4] = 9;

    LB.length = 4;
    LB.data = new int[LB.length];
    LB.data[0] = 2;
    LB.data[1] = 4;
    LB.data[2] = 6;
    LB.data[3] = 8;

    // 调用合并函数
    MergeList_Sq(LA, LB, LC);

    // 输出合并后的结果
    std::cout << "合并后的数组 LC: ";
    for (int i = 0; i < LC.length; ++i) {
        std::cout << LC.data[i] << " ";
    }
    std::cout << std::endl;

    // 释放内存
    delete[] LA.data;
    delete[] LB.data;
    delete[] LC.data;

    return 0;

}

链式表实现

请添加图片描述

  1. 首先用pa,pb工具指针指向链表的第一个节点(不是头节点)
  2. 然后再用LA的头节点作为LC的头节点
  3. 然后用工具指针pc指向LC的头节点。
  4. 当LA和LB都没有抵达表尾的时候,比较LA和LB中的节点数据大小,把小的节点摘取插入到LC的最后。
  5. 然是其中一个抵达表尾,直接将非空表剩余的段落链到pc所指结点之后.
  6. 最后释放一下LB的节点
#include <stdio.h>
#include <stdlib.h>

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

// 创建一个新节点,并初始化数据
LNode* CreateNode(int data)
{
    LNode* newNode = (LNode*)malloc(sizeof(LNode));
    if (newNode)
    {
        newNode->data = data;
        newNode->next = NULL;
    }
    return newNode;
}

// 在链表末尾添加节点
void AppendNode(LinkList &L, int data)
{
    LNode* newNode = CreateNode(data);
    if (newNode)
    {
        LNode* p = L;
        while (p->next)
        {
            p = p->next;
        }
        p->next = newNode;
    }
}

// 打印链表
void PrintList(LinkList L)
{
    LNode* p = L->next;
    while (p)
    {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

// 合并两个有序链表
void MergeList_L(LinkList &LA, LinkList &LB, LinkList &LC)
{
    LNode* pa = LA->next;
    LNode* pb = LB->next;
    LC = LA;  // LC 指向 LA 的头结点
    LNode* pc = LC;

    while (pa && pb)
    {
        if (pa->data <= pb->data)
        {
            pc->next = pa;
            pc = pa;
            pa = pa->next;
        }
        else
        {
            pc->next = pb;
            pc = pb;
            pb = pb->next;
        }
    }

    pc->next = pa ? pa : pb;

    // 删除 LB 指向的链表
    free(LB);
}
int main()
{
    LinkList LA, LB, LC;

    // 初始化 LA 链表
    LA = (LinkList)malloc(sizeof(LNode));
    LA->next = NULL;
    AppendNode(LA, 2);
    AppendNode(LA, 4);
    AppendNode(LA, 6);

    // 初始化 LB 链表
    LB = (LinkList)malloc(sizeof(LNode));
    LB->next = NULL;
    AppendNode(LB, 1);
    AppendNode(LB, 3);
    AppendNode(LB, 5);

    // 初始化 LC 链表
    LC = (LinkList)malloc(sizeof(LNode));
    LC->next = NULL;

    printf("LA: ");
    PrintList(LA);

    printf("LB: ");
    PrintList(LB);

    // 合并 LA 和 LB 到 LC
    MergeList_L(LA, LB, LC);

    printf("LC (Merged): ");
    PrintList(LC);

    // 释放内存
    free(LA);
    free(LC);

    return 0;
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值