学习完最基本的线性表操作,我们开始学习运用这些强大的操作。一开始,大家可能很不习惯使用这些操作,但还是那句话,熟能生巧。只要你肯下功夫,什么都是手到擒来,代码都能变成金块。
我们今天来讲一下这道例题:
假设有两个集合A和B(元素都按非递减有序排列),分别用两个线性表La和Lb表示。利用线性表的基本运算设计一个算法求一个新的集合C,将两个集合的并集放在线性表Lc中,Lc仍按非递减有序排列。
大家有什么奇思妙想?先自己想一想,写一写,画一画。
想好了吗?下面贴我的代码:
SqList* UnionList(SqList La,SqList Lb,SqList* Lc){
//函数的返回值是一个指向SqList结构体类型的指针。
//形式参数包括两个待合并的有序顺序表La和Lb和一个指向未初始化的顺序表的指针Lc,该顺序表用于存放合并后的顺序表。
int i=1,j=1,k=0;
//i和j分别表示顺序表La和Lb中元素的逻辑位置。
//k用来表实顺序表Lc中元素的逻辑位置。
Lc=InitList(Lc);//初始化顺序表Lc。
int ai,bj;//分别用来带出La和Lb顺序表中找到的元素。
while(i<=ListLength(&La)&&j<=ListLength(&Lb)){
//当i尚小于等于顺序表La的长度且j尚小于等于顺序表Lb的长度时,即两个顺序表都没有遍历完成时,持续循环。
GetElem(&La,i,&ai);//取出顺序表La中第i个位置的元素,存放在变量ai中。
GetElem(&Lb,j,&bj);//取出顺序表Lb中第j个位置的元素,存放在变量bj中。
if(ai<bj){//如果La中此刻的元素小于Lb中此刻的元素
ListInsert(Lc,++k,ai);//往顺序表Lc中插入较小的那个。
i++;//元素下标往前移动一位。
}
else if(ai==bj){//如果此刻两个元素相等
ListInsert(Lc,++k,ai);//往Lc中插入元素值。
i++;
j++;//两个顺序表中的元素同时向前移动一位。
}
else{//原理同第一个if语句。
ListInsert(Lc,++k,bj);
j++;
}
}
//循环结束,两个线性表一定至少有一个遍历已经完成。
while(i<=ListLength(&La)){//如果La表未遍历完,执行此循环,否则不执行,进入下一循环。
GetElem(&La,i++,&ai);//取出La中的元素
ListInsert(Lc,++k,ai);//将取出的元素插入Lc中。
}
while(j<=ListLength(&Lb)){//原理同上。
GetElem(&Lb,j++,&bj);
ListInsert(Lc,++k,bj);
}
return Lc;//返回指向已经合并好的顺序表的指针。
}
虽然我写了很详细的注释,但我还是觉得应该进一步讲解才能讲得更透彻。
比如,La是这样一个有序集合:{1,2,3,4,5,6,7,8,9,10},共计10个元素。Lb是:{1,2,4,8,16,32,64},共计7个元素。想要实现它们的并集仍然是一个有序集合,我们应该这样做:各自拿出两个顺序表的第一个元素
比较一下大小,发现元素大小相等,于是把1存入Lc中之后,i和j同时往前移动一位:
这时两个顺序表各自拿出第二个元素:
比较大小,发现元素仍然相等,把2存入Lc后,i和j同时再往前移动一位:
这时,两个顺序表各自拿出第三个元素:
比较大小,发现3比4小,于是把3存入Lc中,i往前移动一个位置,j不动:
这时,拿La的第四个元素和Lb的第三个元素比较大小:
此处省略一万字......
当La遍历结束时:
Lb指向元素16。跳出循环,进入下一个while循环,把所有Lb中剩余的元素取出来插入到Lc的末尾,求并集的过程就算完成了。
我们来用一个完整的程序测试一下:
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#define MaxSize 50
typedef int ElemType;
typedef struct{
ElemType data[MaxSize];
int length;
}SqList;
SqList* InitList(SqList* L){
L=(SqList*)malloc(sizeof(SqList));
L->length=0;
return L;
}
void DestroyList(SqList* L){
free(L);
}
bool ListEmpty(SqList* L){
return(L->length==0);
}
int ListLength(SqList* L){
return(L->length);
}
void DispList(SqList* L){
for(int i=0;i<L->length;i++)
printf("%d\n",L->data[i]);
}
bool GetElem(SqList* L,int i,ElemType *e){
if(i<1||i>L->length)return false;
*e=L->data[i-1];
return true;
}
int LocateElem(SqList* L,ElemType e){
int i=0;
while(i<L->length&&L->data[i]!=e)
i++;
if(i>=L->length)return 0;
else return i+1;
}
bool ListInsert(SqList* L,int i,ElemType e){
int j;
if(i<1||i>L->length+1)return false;
i--;
for(j=L->length;j>i;j--)
L->data[j]=L->data[j-1];
L->data[i]=e;
L->length++;
return true;
}
bool ListDelete(SqList* L,int i,ElemType* e){
int j;
if(i<1||i>L->length)return false;
i--;
*e=L->data[i];
for(j=i;j<L->length-1;j++)
L->data[j]=L->data[j+1];
L->length--;
return true;
}
SqList* CreateList(SqList* L,ElemType a[],int n){
int i=0,k=0;
L = (SqList*)malloc(sizeof(SqList));
while(i < n){
L->data[i]=a[i];
i++;
k++;
}
L->length=k;
return L;
}
SqList* UnionList(SqList La,SqList Lb,SqList* Lc){
int i=1,j=1,k=0;
Lc=InitList(Lc);
int ai,bj;
while(i<=ListLength(&La)&&j<=ListLength(&Lb)){
GetElem(&La,i,&ai);
GetElem(&Lb,j,&bj);
if(ai<bj){
ListInsert(Lc,++k,ai);
i++;
}
else if(ai==bj){
ListInsert(Lc,++k,ai);
i++;
j++;
}
else{
ListInsert(Lc,++k,bj);
j++;
}
}
while(i<=ListLength(&La)){
GetElem(&La,i++,&ai);
ListInsert(Lc,++k,ai);
}
while(j<=ListLength(&Lb)){
GetElem(&Lb,j++,&bj);
ListInsert(Lc,++k,bj);
}
return Lc;
}
int main(int argc, char const *argv[])
{
SqList *La,*Lb,*Lc;
int a[10]={1,2,3,4,5,6,7,8,9,10};
int b[7]={1,2,4,8,16,32,64};
La=CreateList(La,a,10);
Lb=CreateList(Lb,b,7);
Lc=UnionList(*La,*Lb,Lc);
DispList(Lc);
return 0;
}
运行结果如下:
没有一个元素落下,没有任何两个元素重复,证明我们的试验成功了。
你还有什么更好的方法吗?欢迎留言交流!
来源:CSDN
作者:人间小辣鸡
链接:https://blog.csdn.net/weixin_45264145/article/details/104733075