导读

  • 顺序表归并的方式及其特点
  • 实现“归并”操作
  • 实现“并”操作
  • 完整代码(归并与并)

归并发的方式及特点:

设有两个顺序表La Lb,Lc=La U Lb

归并:即是将La归并到Lb表中且仍保持有序(保留相同元素)

并:即是将La和Lb并存到Lc中且相同元素不保留

归并操作实现:

详情见注解

void MergeList2(SqList La, SqList &Lb, SqList &Lc)
{
int *pa, *pa_last, *pb, *pb_last, *pc;
pa = La.elem;//pa为LA 的基地址
pb = Lb.elem;
Lc.listsize = Lc.length = La.length + Lb.length;//不用InitList()创建空表Lc
pc = Lc.elem = (int *)malloc(Lc.listsize*sizeof(int));//动态分配空间
if (!Lc.elem) // 存储分配失败
exit(0);
pa_last = La.elem + La.length - 1;//pa_last为LA的尾地址
pb_last = Lb.elem + Lb.length - 1;
while (pa <= pa_last&&pb <= pb_last) // 表La和表Lb均非空
{ // 归并
if (*pa <= *pb)//Lb的元素大就先插LA的
*pc++ = *pa++;
else
*pc++ = *pb++;//反之
}
while (pa <= pa_last) // 表La非空且表Lb空
*pc++ = *pa++; //La剩下的顺序插入
while (pb <= pb_last) //同上
*pc++ = *pb++;
}

 

并操作实现:

与归并操作基本一致,不一致的地方已标记,注解不再重复给出

详情见头顶上注解

void MergeList1(SqList La, SqList Lb, SqList &Lc)
{
int *pa, *pa_last, *pb, *pb_last, *pc;
pa = La.elem;
pb = Lb.elem;
Lc.listsize = Lc.length = La.length + Lb.length;
pc = Lc.elem = (int *)malloc(Lc.listsize*sizeof(int));
if (!Lc.elem)
exit(0);
pa_last = La.elem + La.length - 1;
pb_last = Lb.elem + Lb.length - 1;
while (pa <= pa_last&&pb <= pb_last) // 表La和表Lb均非空
{ // 归并
if (*pa < *pb)
*pc++ = *pa++;
else if (*pa > *pb)
*pc++ = *pb++;
else{
*pc++ = *pa++;//用*pb++;效果一致
pb++;//用*pb++;效果一致
Lc.length--;//长度减一
}
}
while (pa <= pa_last) // 表La非空且表Lb空
*pc++ = *pa++; // La剩下的顺序插入
while (pb <= pb_last)
*pc++ = *pb++;
}

完整代码:

/*

** 各变量的含义
* elem 基地址
* length 长度
* listsize 当前分配的存储容量
* LIST_INIT_SIZE 存储空间的初始分配量
* LISTINCREMENT 空间不足时分配增量
* newbase 存储容量增加后的新基地址
* SqList 结构体的名称
* pa_last La尾地址
* pb_last Lb尾地址
*/

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

#define LIST_INIT_SIZE 10 // 线性表存储空间的初始分配量
#define LISTINCREMENT 2 // 线性表存储空间的分配增量

struct SqList
{
int *elem;
int length;
int listsize; // 当前分配的存储容量(以sizeof(int)为单位)
};

void InitList(SqList &L)
{
L.elem = (int *)malloc(LIST_INIT_SIZE*sizeof(int));
if (!L.elem)
exit(0);
L.length = 0;
L.listsize = LIST_INIT_SIZE; // 初始存储容量为10
}

int ListInsert(SqList &L, int i, int e)
{
// 初始条件:顺序线性表L已存在,1≤i≤ListLength(L)+1
// 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1
int *newbase, *q, *p;
if (i<1 || i>L.length + 1)
return 0;
if (L.length >= L.listsize) // 当前存储空间已满,以2的倍数增加分配
{
if (!(newbase = (int *)realloc(L.elem, (L.listsize + LISTINCREMENT)*sizeof(int))))
exit(0);
L.elem = newbase;
L.listsize += LISTINCREMENT;
}
q = L.elem + i - 1;
for (p = L.elem + L.length - 1; p >= q; --p)
*(p + 1) = *p;
*q = e; // 插入e
++L.length; // 表长增1
return 1;
}

void Print(SqList &L)
{
int i;
for (i = 0; i<L.length; i++)
printf("%d ", *(L.elem + i));
printf("\n");
}

void MergeList1(SqList La, SqList Lb, SqList &Lc)
{
int *pa, *pa_last, *pb, *pb_last, *pc;
pa = La.elem;
pb = Lb.elem;
Lc.listsize = Lc.length = La.length + Lb.length;//不用InitList()创建空表Lc
pc = Lc.elem = (int *)malloc(Lc.listsize*sizeof(int));
if (!Lc.elem) // 存储分配失败
exit(0);
pa_last = La.elem + La.length - 1;
pb_last = Lb.elem + Lb.length - 1;
while (pa <= pa_last&&pb <= pb_last) // 表La和表Lb均非空
{ // 归并
if (*pa < *pb)
*pc++ = *pa++;
else if (*pa > *pb)
*pc++ = *pb++;
else//相等元素长度减一
{
*pc++ = *pa++;
*pb++;
Lc.length--;
}
}
//一个表已经完成归并,将另一个表元素顺序插入新表
while (pa <= pa_last)
*pc++ = *pa++;
while (pb <= pb_last)
*pc++ = *pb++;
}

void MergeList2(SqList La, SqList &Lb, SqList &Lc)
{
int *pa, *pa_last, *pb, *pb_last, *pc;
pa = La.elem;
pb = Lb.elem;
Lc.listsize = Lc.length = La.length + Lb.length;//不用InitList()创建空表Lc
pc = Lc.elem = (int *)malloc(Lc.listsize*sizeof(int));
if (!Lc.elem) // 存储分配失败
exit(0);
pa_last = La.elem + La.length - 1;
pb_last = Lb.elem + Lb.length - 1;
while (pa <= pa_last&&pb <= pb_last) // 表La和表Lb均非空
{ // 并操作 元素相同时不用长度减一且保留插入
if (*pa <= *pb)
*pc++ = *pa++;
else
*pc++ = *pb++;
}
//一个表已经完成并操作,将另一个表元素顺序插入新表
while (pa <= pa_last)
*pc++ = *pa++;
while (pb <= pb_last)
*pc++ = *pb++;
Lb.length = Lc.length;
Lb = Lc;
}

int main(){
SqList LA, LB, LC;
int a[5] = { 1,2,3,4,5}, b[6] = { 2, 3, 4, 5, 6, 7 };
int i;
InitList(LA);
InitList(LB);
InitList(LC);
for (i = 0; i < 5; i++)
ListInsert(LA, i + 1, a[i]);//依次插入到顺序表中
for (i = 0; i < 6; i++)
ListInsert(LB, i + 1, b[i]);
//原始值
printf("LA=");
Print(LA);
printf("LB=");
Print(LB);
printf("\n");
//并操作
MergeList1(LA, LB, LC);
printf("并:LC=");
Print(LC);
printf("\n");
//归并操作
MergeList2(LA, LB, LC);
printf("归并:LC=");
Print(LC);
printf("\n")

}

 

 


初闻不知曲中意,再听已是曲中人