有序线性表的交集
- 说明
- 2.25 假设两个元素依值递增有序排列的线性表A和B
说明
- 本文参照严蔚敏《数据结构(C语言版)题集》一书中包含的问答题和算法设计题目,提供解答和算法的解决方案。
- 请读者在自己已经解决了某个题目或进行了充分的思考之后,再参考本解答,以保证复习效果。
- 由于作者水平所限,本解答中一定存在不少这样或者那样的错误和不足,希望读者们在阅读中多动脑、勤思考,争取发现和纠正这些错误,写出更好的算法来。
2.25 假设两个元素依值递增有序排列的线性表A和B
分别表示两个集合,
且同一表中的元素值各不相同,
现要求另辟空间构成一个线性表C,
其元素为A和B中元素的交集,
且表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_SqStatus 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); // 表长增1return OK;
}// ListInsert_SqStatus FreeList_Sq(SqList *pL){// 释放线性表if(NULL!=(*pL).elem){free((*pL).elem);return OK;}else{return ERROR;}
}// FreeList_Sqint 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已经做到最简。