算法——有序表的合并
概念解释:
有序集合:集合中元素按值非递减排列。
问题描述:
现在有有两个有序结合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)
插入之后,较小的那个数的指针向后移动。
代码实现
顺序表实现
-
先确定C链表的长度,申请所需空间
-
然后创建三个工具指针分别指向三个表的首元素。
-
然后再创建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;
}
链式表实现
- 首先用pa,pb工具指针指向链表的第一个节点(不是头节点)
- 然后再用LA的头节点作为LC的头节点
- 然后用工具指针pc指向LC的头节点。
- 当LA和LB都没有抵达表尾的时候,比较LA和LB中的节点数据大小,把小的节点摘取插入到LC的最后。
- 然是其中一个抵达表尾,直接将非空表剩余的段落链到pc所指结点之后.
- 最后释放一下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;
}