0
点赞
收藏
分享

微信扫一扫

数据结构题集-第二章-线性表-算法设计题三四

小安子啊 2024-11-06 阅读 7

说明

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

2.12 设 A = ( a 1 , ⋯ , a m ) A=(a_1,\cdots{,}a_m) A=(a1,,am) B = ( b 1 , ⋯ , b n ) B=(b_1,\cdots{,}b_n) B=(b1,,bn)均为顺序表

A ′ A' A B ′ B' B分别为 A A A B B B中除去最大共同前缀后的子表,
例如, A = ( x , y , y , z , x , z ) A=(x,y,y,z,x,z) A=(x,y,y,z,x,z) B = ( x , y , y , z , y , x , x , z ) B=(x,y,y,z,y,x,x,z) B=(x,y,y,z,y,x,x,z)
则两者中最大的共同前缀为 ( x , y , y , z ) (x,y,y,z) (x,y,y,z)
在两表中除去最大公共前缀后的子表分别为:
A ′ = ( x , z ) A'=(x,z) A=(x,z) B ′ = ( y , x , x , z ) B'=(y,x,x,z) B=(y,x,x,z)
A ′ = B ′ = A'=B'= A=B=空表,则 A = B A=B A=B
A ′ = A'= A=空表,而 B ′ ≠ B'\ne B=空表,或者两者均不为空表,
A ′ A' A的首元小于 B ′ B' B的首元,则 A < B A<B A<B;否则 A > B A>B A>B
试写一个比较 A , B A,B A,B大小的算法;
请注意:在算法中,不要破坏原表 A A A B B B,并且,也不一定先求得 A ′ A' A B ′ B' B才进行比较。

解:
用同一个下标变量控制两个线性表。注意你的算法对空表也应能正确执行。

#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 50
#define MAX_TEST_ELEM 26
typedef char 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

Status rand_init_two_list(SqList *pL, SqList *qL){
	time_t t;
	int c1,c2,count = MAX_TEST_LENGTH;
	if(OK!=InitList_Sq(pL)) return ERROR;
	if(OK!=InitList_Sq(qL)) return ERROR;
	
	srand((unsigned)time(&t)); //初始化随机数发生器
	
	c1 = rand()%MAX_TEST_LENGTH;
	while(c1--){
		if(OK!=ListInsert_Sq(pL,1+rand()%((*pL).length+1),'A'+(rand()%MAX_TEST_ELEM)))
			return ERROR; // 随机找一个合法位置插入新随机元素
	}
	
	c2 = rand()%MAX_TEST_LENGTH;
	while(c2--){
		if(OK!=ListInsert_Sq(qL,1+rand()%((*qL).length+1),'A'+(rand()%MAX_TEST_ELEM)))
			return ERROR; // 随机找一个合法位置插入新随机元素
	}
	
	return OK;
}

void display_two_list(SqList La, SqList Lb){
	int i;
	printf("List A:\n");
	if(!La.length) printf("List A is empty.");
	for(i=1;i<=La.length;i++){
		printf("%c",La.elem[i-1]);
	}
	printf("\nList B:\n");
	if(!Lb.length) printf("List B is empty.\n");
	for(i=1;i<=Lb.length;i++){
		printf("%c",Lb.elem[i-1]);
	}
	putchar('\n');
}

void the_same_prefix(SqList *pL, SqList *qL){
	// 随机使两表有相同前缀
	time_t t;
	int len,choice;
	srand((unsigned)time(&t));
	len=(*pL).length<(*qL).length?(*pL).length:(*qL).length;

	len=rand()%(len+1);
	
	choice = rand()%2;
	if(choice) (*pL).length=(*qL).length=len;
	while(len--) (*pL).elem[len]=(*qL).elem[len];
}

void test_list_null(SqList *pL, SqList *qL){
	// 随机将两表长度变为0,为空表 
	time_t t;
	srand((unsigned)time(&t));
	int choice = rand()%3;
	if(choice==0){
		(*pL).length=0;
	}else if(choice==1){
		(*qL).length=0;
	}else{
		(*pL).length=(*qL).length=0;
	}
}

void free_two_list(SqList *pL, SqList *qL){
	if(OK==FreeList_Sq(pL))
		printf("\nFree List A success!");
	if(OK==FreeList_Sq(qL))
		printf("\nFree List B success!\n");
}

int ListComp(SqList A,SqList B){
	int i;
	//比较字符表A和B,并用返回值表示结果,值为1,表示A>B;值为-1,表示A<B;值为0,表示A=B
	for(i=0;i<A.length&&i<B.length;i++)
		if(A.elem[i]!=B.elem[i])
			return A.elem[i]>B.elem[i]?1:-1;
	if(A.length==B.length) return 0;
		//当两个字符表可以互相比较的部分完全相同时,哪个较长,哪个就较大
		return A.length>B.length?1:-1;
}//ListComp


int main(){
	SqList La,Lb;
	int result;
	if(OK==rand_init_two_list(&La,&Lb)){
		display_two_list(La,Lb);
		result=ListComp(La,Lb);
		if(result==1) printf("A>B\n");
		else if(result==-1) printf("A<B\n");
		else printf("A=B\n");
		
		putchar('\n');
		// 测试两表有相同前缀,有可能相等
		the_same_prefix(&La,&Lb);
		display_two_list(La,Lb);
		result=ListComp(La,Lb);
		if(result==1) printf("A>B\n");
		else if(result==-1) printf("A<B\n");
		else printf("A=B\n");
		
		putchar('\n');
		// 测试随机将其中一个表变空,或者两表都为空
		test_list_null(&La,&Lb);
		display_two_list(La,Lb);
		result=ListComp(La,Lb);
		if(result==1) printf("A>B\n");
		else if(result==-1) printf("A<B\n");
		else printf("A=B\n");
		
		free_two_list(&La,&Lb);
	}
	return 0;
}

2.13 试写一算法

在带头结点的单链表结构上实现线性表操作LOCATE(L,X)。

解:
上面用动态开辟空间建立和扩展数组,这里用数组来表达静态链表,为什么会这样?
这和我们通常遇到问题的规模有关,一般需要存在数组中可顺序随机存取的数据,
往往需要很大的空间,这样空间的大小往往是我们预料不到的,
所以不得不求助链式开辟,获得一个相对较大的堆空间,而不会形成碎片。
但是链表不一样,互相之间有链式关系的模式通常是有限的,其规模是可以预测到的,
比如树、图和网。所以,从动态数组到静态链表,它们各自取长补短、相辅相成。

#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 MAXSIZE 20
typedef int ElemType;

typedef struct{
	ElemType data;
	int cur;
}component, SLinkList[MAXSIZE];

#define MAX_TEST_ELEM 1000

void InitSpace_SL(SLinkList space){
	// 将一维数组space中各分量链成一个备用链表
	// space[0].cur为头指针,0表示空指针
	int i;
	for(i=0;i<MAXSIZE-1;++i) space[i].cur=i+1;
	space[MAXSIZE-1].cur=0;
} // InitSpace_SL

void rand_init_space_data(SLinkList space){
	// 随机生成静态链表中每个元素的数据
	int i;
	time_t t;
	
	srand((unsigned)time(&t)); //初始化随机数发生器
	for(i=0;i<MAXSIZE;++i) space[i].data=rand()%MAX_TEST_ELEM;
}

void init_order_space_data(SLinkList space){
	// 有序生成静态链表中每个元素的数据
	int i;
	for(i=0;i<MAXSIZE;++i) space[i].data=i;
}

void display_space(SLinkList space){
	// 显示静态链表
	int i;
	for(i=space[0].cur;i;i=space[i].cur)
		printf("space[%d].data=%d,next=%d\n",i,space[i].data,space[i].cur);
}

int LocateElem_SL(SLinkList s,ElemType x){
	// 在静态链表中查找第一个值为x的元素
	// 若找到,则返回它在链表中的位序,否则返回0
	int i;
	for(i=s[0].cur;i&&s[i].data!=x;i=s[i].cur);
	return i;
}
int main(){
	int x;
	SLinkList space;
	InitSpace_SL(space);
	printf("Ordered List:\n");
	init_order_space_data(space);
	display_space(space);
	
	printf("\nRand List's data:\n");
	rand_init_space_data(space);
	display_space(space);
	
	printf("Input x and locate its position:");
	scanf("%d",&x);
	printf("Locate x in List,pos=%d",LocateElem_SL(space,x));
	return 0;
}
举报

相关推荐

0 条评论