数据结构题集-第二章-线性表-有序线性表的交集

有序线性表的交集

  • 说明
  • [2.25 假设两个元素依值递增有序排列的线性表A和B](#2.25 假设两个元素依值递增有序排列的线性表A和B)

说明

  • 本文参照严蔚敏《数据结构(C语言版)题集》一书中包含的问答题和算法设计题目,提供解答和算法的解决方案。
  • 请读者在自己已经解决了某个题目或进行了充分的思考之后,再参考本解答,以保证复习效果。
  • 由于作者水平所限,本解答中一定存在不少这样或者那样的错误和不足,希望读者们在阅读中多动脑、勤思考,争取发现和纠正这些错误,写出更好的算法来。

2.25 假设两个元素依值递增有序排列的线性表A和B

分别表示两个集合,

且同一表中的元素值各不相同,

现要求另辟空间构成一个线性表C,

其元素为A和B中元素的交集,

且表C中的元素也依值递增有序排列。

试对线性表编写求C的算法。

解:

争取作最少比较就可以从两个递增线性表中提取仍然有序的交集:

c 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;

#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10

#define MAX_TEST_LENGTH 20
#define MAX_TEST_ELEM 20
typedef int ElemType;
typedef struct{
	ElemType *elem; // 存储空间基址
	int length; // 当前长度
	int listsize; // 当前分配的存储容量
} SqList; // 顺序表类型
typedef struct LNode{
	ElemType data;
	struct LNode *next;
} LNode, *LinkList; // 线性链表类型

Status InitList_Sq(SqList *pL){
	// 构造一个空的线性表
	(*pL).elem = (ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));
	if(!(*pL).elem) exit(OVERFLOW); // 存储分配失败
	(*pL).length = 0; // 空表长度为0
	(*pL).listsize = LIST_INIT_SIZE; // 初始存储容量
	return OK;
}// InitList_Sq

Status ListInsert_Sq(SqList *pL, int i, ElemType e){
	// 在顺序线性表L中第i个位置之前插入新的元素e
	// i的合法值范围:[1,ListLength_Sq(L)+1]
	if(i<1 || i>((*pL).length+1)) return ERROR; // i值不合法
	if((*pL).length>=(*pL).listsize){ // 当前存储空间已满,增加分配
		ElemType *newbase = (ElemType *)realloc((*pL).elem,((*pL).listsize+LISTINCREMENT)*sizeof(ElemType));
		if(!newbase) exit(OVERFLOW); // 存储分配失败
		(*pL).elem = newbase; // 新基址
		(*pL).listsize += LISTINCREMENT; // 增加存储容量
	}
	ElemType *p = NULL;
	ElemType *q = &((*pL).elem[i-1]); // q为插入位置
	for(p=&((*pL).elem[(*pL).length-1]);p>=q;--p) *(p+1) = *p; // 插入位置及之后的元素右移
	*q = e; // 插入e
	++((*pL).length); // 表长增1
	return OK;
}// ListInsert_Sq

Status FreeList_Sq(SqList *pL){
	// 释放线性表
	if(NULL!=(*pL).elem){
		free((*pL).elem);
		return OK;
	}else{
		return ERROR;
	}
}// FreeList_Sq

int InsertOrderSqList(SqList *pL,int x){
	//把x插入递增有序表pL中,并返回插入的位置(数组下标)
	int i;
	if((*pL).length+1>(*pL).listsize) return OVERFLOW;
	(*pL).length++;
	for(i=(*pL).length-1;(*pL).elem[i]>x&&i>=0;i--)
		(*pL).elem[i+1]=(*pL).elem[i];
	(*pL).elem[i+1]=x;
	return i+1;
}//InsertOrderSqList 

int cmp(const void *x,const void *y){
	// qsort函数需要调用的比较函数
	ElemType *a=(ElemType *)x; 
	ElemType *b=(ElemType *)y;
    return (*a-*b);
}

void intersect_set(SqList A,SqList B,SqList *pC){
	//元素递增排列的线性表A和B中元素交集合并存入C中,仍保持有序
	int i,j,k;
	i=j=k=0;
	while(i<A.length&&j<B.length){
		if(A.elem[i]<B.elem[j]) i++;
		else if(A.elem[i]>B.elem[j]) j++;
		else{
			pC->elem[k++]=A.elem[i];
			pC->length++;
			i++;
			j++;
		}
	}
}

void sorted_list_to_set(SqList *pL){
	//在顺序线性表中去除重复元素,成为集合
	int i,j,k,d;
	for(i=0;i<pL->length;i++){
		k=i;
		for(j=i+1;(j<pL->length)&&(pL->elem[j]==pL->elem[i]);j++);
		if(j>i+1){
			d=j-i-1;
			while(j<pL->length){
				pL->elem[++k]=pL->elem[j++];
			}
			pL->length -= d;
		}
	}
}

void display_list(SqList L){
	int i;
	for(i=1;i<=L.length;i++){
		printf("%3d.%d\t",i-1,L.elem[i-1]);
		if(i%7==0) putchar('\n');
	}
}

Status rand_create_sorted_sets(SqList *pA, SqList *pB){
	int pos,dupli_rand_count,dupli_rand_num;
	time_t t;
	int count;
	
	srand((unsigned)time(&t)); //初始化随机数发生器
	
	count = rand()%MAX_TEST_LENGTH;
	while(count--){
		dupli_rand_count=rand()%10;
		dupli_rand_num=rand()%MAX_TEST_ELEM;
		while(dupli_rand_count--){
			if(OK!=ListInsert_Sq(pA,1+rand()%((*pA).length+1),dupli_rand_num))
				return ERROR; // 随机找一个合法位置插入新随机元素
		}
	}
	qsort((*pA).elem,(*pA).length,sizeof(ElemType),cmp);
	//printf("\nSqList A:\n");
	//display_list(*pA);
	sorted_list_to_set(pA);
	printf("\nA:\n");
	display_list(*pA);
	
	count = rand()%MAX_TEST_LENGTH;
	while(count--){
		dupli_rand_count=rand()%10;
		dupli_rand_num=rand()%MAX_TEST_ELEM;
		while(dupli_rand_count--){
			if(OK!=ListInsert_Sq(pB,1+rand()%((*pB).length+1),dupli_rand_num))
				return ERROR; // 随机找一个合法位置插入新随机元素
		}
	}
	qsort((*pB).elem,(*pB).length,sizeof(ElemType),cmp);
	//printf("\nSqList B:\n");
	//display_list(*pB);
	sorted_list_to_set(pB);
	printf("\nB:\n");
	display_list(*pB);
	return OK;
}

int main(){
	ElemType x;
	SqList La,Lb,Lc;
	if(OK!=InitList_Sq(&La)) return ERROR;
	if(OK!=InitList_Sq(&Lb)) return ERROR;
	if(OK!=InitList_Sq(&Lc)) return ERROR;
	
	if(OK!=rand_create_sorted_sets(&La,&Lb)) return ERROR;
	
	intersect_set(La,Lb,&Lc);
	printf("\nC:\n");
	display_list(Lc);

	if(OK==FreeList_Sq(&La))
		printf("\nFree SqList A success!\n");
	if(OK==FreeList_Sq(&Lb))
		printf("\nFree SqList B success!\n");
	if(OK==FreeList_Sq(&Lc))
		printf("\nFree SqList C success!\n");
	return 0;
}

测试数据基本符合题目的要求,其中去重的算法sorted_list_to_set已经做到最简。

相关推荐
XH华1 小时前
初识C语言之二维数组(下)
c语言·算法
南宫生1 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
不想当程序猿_2 小时前
【蓝桥杯每日一题】求和——前缀和
算法·前缀和·蓝桥杯
落魄君子2 小时前
GA-BP分类-遗传算法(Genetic Algorithm)和反向传播算法(Backpropagation)
算法·分类·数据挖掘
菜鸡中的奋斗鸡→挣扎鸡2 小时前
滑动窗口 + 算法复习
数据结构·算法
Lenyiin2 小时前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin
郭wes代码2 小时前
Cmd命令大全(万字详细版)
python·算法·小程序
scan7242 小时前
LILAC采样算法
人工智能·算法·机器学习
菌菌的快乐生活3 小时前
理解支持向量机
算法·机器学习·支持向量机
大山同学3 小时前
第三章线性判别函数(二)
线性代数·算法·机器学习