顺序表的基本操作——归并

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;
} 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值