1、【算法2.1】假设:有两个集合 A 和 B 分别用两个线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合A=A∪B。
具体操作:扩大线性表 LA,将存在于线性表LB 中而不存在于线性表 LA 中的数据元素插入到线性表 LA 中去。
代码实现:合并的代码:Union
#include<stdio.h>
#include<stdlib.h>
typedef int Status; //状态码识别类型
typedef int ElemType;
#define LIST_INIT_SIZE 100 //顺序表存储空间的初始分配量
#define LISTINCREMENT 10 //顺序表存储空间的分配增量
#define OVERFLOW -2 //堆栈上溢
#define UNDERFLOW -3 //堆栈下溢
//△01 线性表的动态分配顺序存储结构
typedef struct{
ElemType *elem;//存储空间基地址
int length; //当前长度
int listsize; //当前分配的存储空间大小(以sizeof(ElemType)为单位)
}SqList;
//△02初始化,构造一个空的线性表L
Status InitList_Sq(SqList &L){
L.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if(!L.elem){//存储分配失败, ☆exit结束进程,将OVERFLOW的值返回给操作系统
exit(OVERFLOW);
}
L.length=0;
L.listsize=LIST_INIT_SIZE;
return 1;
}
//△03在第i个位置(L.elem[i-1])插入值为x的数据元素
Status ListInsert_Sq(SqList &L,int i,ElemType e){
if(i<1||i>L.length+1){
return 0;
}
ElemType *newbase;
ElemType *p,*q;
//当前存储空间已满,增加分配
if(L.length>=L.listsize){
newbase=(ElemType*)realloc(L.elem,
(L.listsize+LISTINCREMENT)*sizeof(ElemType));
if(!newbase){
exit(OVERFLOW);
}
L.elem=newbase;//新基址
L.listsize+=LISTINCREMENT;//增加存储容量
}
q=&(L.elem[i-1]);//q为插入位置
for(p=&(L.elem[L.length-1]);p>=q;p--){
*(p+1)=*p; //右移
}
*q=e;
L.length++;
return 1;
}
void PrintElem(ElemType e){
printf("%d ", e);
}//△05遍历顺序表
Status ListTraverse_Sq(SqList L,void (visit)(ElemType)){
for(int i=0;i<L.length;i++){
visit(L.elem[i]);
}
printf("\n");
return 1;
}
//△09顺序表L中的元素个数
int ListLength_Sq(SqList L){
return L.length;
}
//△10返回第i个元素的值
Status GetElem_Sq(SqList L,int i,ElemType *e){
if(i<1||i>L.length){
return 0;
}
*e=L.elem[i-1];
return 1;
}
Status CmpEqual(ElemType e, ElemType data){
return data==e?true:false;
}//△11 返回L中第一个与e满足关系compare()的数据元素的位序
int LocateElem_Sq(SqList L, ElemType e, Status (Compare)(ElemType,ElemType)){
int i = 1; //i的初值为第一个元素的位序
ElemType *p=L.elem; //p的初值为第一个元素的存储位置
while(i<=L.length&&!Compare(e,*p++)){
i++;
}
if(i<=L.length){
return i;
}else{
return 0;
}
}
void Union(SqList &La,SqList Lb){
int La_len=ListLength_Sq(La);
int Lb_len=ListLength_Sq(Lb);
ElemType e;
La_len=La_len+1;//或者内层写++La_len
for(int i=1;i<=Lb_len;i++){
GetElem_Sq(Lb,i,&e);//取Lb中第i个数据元素赋给e
if(!LocateElem_Sq(La,e,CmpEqual)){//La中不存在和e相同的数据元素
ListInsert_Sq(La,La_len++,e);
}
}
}
int main(){
SqList La,Lb;
ElemType a[6]={0,1,6,7,8,9};
ElemType b[7] = {1,2,3,4,5,6,10};
int i;
InitList_Sq(La); //初始化La
for(i=1;i<=6;i++){
ListInsert_Sq(La,i,a[i-1]);
}
InitList_Sq(Lb); //初始化Lb
for(i=1;i<=7; i++){
ListInsert_Sq(Lb,i,b[i-1]);
}
printf("La= "); ListTraverse_Sq(La, PrintElem);
printf("Lb= "); ListTraverse_Sq(Lb, PrintElem);
printf("La=La∪Lb = "); //输出新表La的内容
Union(La,Lb);
ListTraverse_Sq(La,PrintElem);
return 0;
}
2、【算法2.2 & 2.7】已知线性表LA和LB中的数据元素按值非递减有序排列,现要求将LA和LB归并为一个新的线性表LC,且LC中的数据元素仍按值非递减有序排列。
具体操作:先设LC为空表,然后将LA或LB中的元素逐个插入到LC中即可。
代码实现:合并的代码:MergeList1_Sq、MergeList2_Sq
算法2.2 时间复杂度为O(ListLength(LA)+ListLength(LB)),算法2.7 时间复杂度为O(La.length+Lb.length)
#include<stdio.h>
#include<stdlib.h>
typedef int Status; //状态码识别类型
typedef int ElemType;
#define LIST_INIT_SIZE 100 //顺序表存储空间的初始分配量
#define LISTINCREMENT 10 //顺序表存储空间的分配增量
#define OVERFLOW -2 //堆栈上溢
#define UNDERFLOW -3 //堆栈下溢
//△01 线性表的动态分配顺序存储结构
typedef struct{
ElemType *elem;//存储空间基地址
int length; //当前长度
int listsize; //当前分配的存储空间大小(以sizeof(ElemType)为单位)
}SqList;
//△02初始化,构造一个空的线性表L
Status InitList_Sq(SqList &L){
L.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if(!L.elem){//存储分配失败, ☆exit结束进程,将OVERFLOW的值返回给操作系统
exit(OVERFLOW);
}
L.length=0;
L.listsize=LIST_INIT_SIZE;
return 1;
}
//△03在第i个位置(L.elem[i-1])插入值为x的数据元素
Status ListInsert_Sq(SqList &L,int i,ElemType e){
if(i<1||i>L.length+1){
return 0;
}
ElemType *newbase;
ElemType *p,*q;
//当前存储空间已满,增加分配
if(L.length>=L.listsize){
newbase=(ElemType*)realloc(L.elem,
(L.listsize+LISTINCREMENT)*sizeof(ElemType));
if(!newbase){
exit(OVERFLOW);
}
L.elem=newbase;//新基址
L.listsize+=LISTINCREMENT;//增加存储容量
}
q=&(L.elem[i-1]);//q为插入位置
for(p=&(L.elem[L.length-1]);p>=q;p--){
*(p+1)=*p; //右移
}
*q=e;
L.length++;
return 1;
}
void PrintElem(ElemType e){
printf("%d ", e);
}
//△05遍历顺序表
Status ListTraverse_Sq(SqList L,void (visit)(ElemType)){
for(int i=0;i<L.length;i++){
visit(L.elem[i]);
}
printf("\n");
return 1;
}
//△09顺序表L中的元素个数
int ListLength_Sq(SqList L){
return L.length;
}
//△10返回第i个元素的值
Status GetElem_Sq(SqList L,int i,ElemType *e){
if(i<1||i>L.length){
return 0;
}
*e=L.elem[i-1];
return 1;
}
//【算法2.2】
void MergeList1_Sq(SqList La,SqList Lb,SqList &Lc){
ElemType ai,bj;
int i=1,j=1,k=0;
InitList_Sq(Lc);
int La_len=ListLength_Sq(La);
int Lb_len=ListLength_Sq(Lb);
while((i<=La_len)&&(j<=Lb_len)){ // La和Lb均非空
GetElem_Sq(La,i,&ai);
GetElem_Sq(Lb,j,&bj);
if(ai<=bj){
ListInsert_Sq(Lc,++k,ai);
++i;
} else{
ListInsert_Sq(Lc,++k,bj);
++j;
}
}
while(i<=La_len){
GetElem_Sq(La,i++,&ai);
ListInsert_Sq(Lc,++k,ai);
}
while(j<=Lb_len){
GetElem_Sq(Lb,j++,&bj);
ListInsert_Sq(Lc,++k,bj);
}
}
//【算法2.7】
void MergeList2_Sq(SqList La,SqList Lb,SqList &Lc){
ElemType *pa,*pb,*pc,*pa_last,*pb_last;
pa=La.elem;
pb=Lb.elem;
Lc.listsize=Lc.length=La.length+Lb.length;
pc=Lc.elem=(ElemType*)malloc(Lc.listsize*sizeof(ElemType));
if(!Lc.elem){
exit(OVERFLOW);
}
pa_last=La.elem+La.length-1;
pb_last=Lb.elem+Lb.length-1;
while(pa<=pa_last&&pb<=pb_last){ // 归并
if(*pa<=*pb){
*pc++=*pa++;
}else{
*pc++=*pb++;
}
}
while(pa<=pa_last){
*pc++=*pa++; // 插入La的剩余元素
}
while(pb<=pb_last){
*pc++=*pb++; // 插入Lb的剩余元素
}
}
int main(){
SqList La,Lb,Lc1,Lc2;
ElemType a[6]={0,1,6,7,8,9};
ElemType b[7]={1,2,3,4,5,6,10};
int i;
InitList_Sq(La); //初始化La
for(i=1;i<=6;i++){
ListInsert_Sq(La,i,a[i-1]);
}
InitList_Sq(Lb); //初始化Lb
for(i=1;i<=7; i++){
ListInsert_Sq(Lb,i,b[i-1]);
}
printf("La= "); ListTraverse_Sq(La, PrintElem);
printf("Lb= "); ListTraverse_Sq(Lb, PrintElem);
printf("合并La和Lb:Lc1= "); //输出Lc1
MergeList1_Sq(La,Lb,Lc1);
ListTraverse_Sq(Lc1,PrintElem);
printf("合并La和Lb:Lc2= "); //输出Lc2
MergeList1_Sq(La,Lb,Lc2);
ListTraverse_Sq(Lc2,PrintElem);
return 0;
}