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

说明

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

2.11 设顺序表va中的数据元素递增有序

试写一算法,将x插入到顺序表的适当位置上,以保持该表的有序性。

解:

此题的算法思想:

(1) 查找 x x x在顺序表 a . e l e m [ a . l e n g t h ] a.elem[a.length] a.elem[a.length]中的插入位置,即求满足 a . e l e m [ i ] ≤ x < a . e l e m [ i + 1 ] a.elem[i]\le{x}<a.elem[i+1] a.elem[i]≤x<a.elem[i+1],
e l e m [ i + 1 ] elem[i+1] elem[i+1]的 i i i值( i i i的初值为 a . l e n g t h − 1 a.length-1 a.length−1);

(2) 将顺序表中的 a . l e n g t h − i − 1 a.length-i-1 a.length−i−1个元素 a . e l e m [ i + 1 ⋯ a . l e n g t h − 1 ] a.elem[i+1\cdots{a.length-1}] a.elem[i+1⋯a.length−1]后移一个位置;

(3) 将 x x x插入到 e . e l e m [ i + 1 ] e.elem[i+1] e.elem[i+1]中且将表长 a . l e n g t h a.length a.length加 1 1 1。

上述算法正确执行的参数条件为: 0 ≤ a . l e n g t h < a . l i s t s i z e 0\le{a.length}<a.listsize 0≤a.length<a.listsize。

算法的伪代码如下:

c 复制代码
Status InsertOrderList(SqList &a,ElemType x)
{
	// 顺序表a中的元素依值递增有序,本算法将x插入其中适当位置
	// 以保持其有序性。入口断言:0<=a.length<a.listsize
	if(a.length==a.listsize) return (OVERFLOW);
	else{
		i=a.length-1;
		while(i>=0&&x<a.elem[i]) i--; // 查找x的插入位置
		// i<0 || x>=a.elem[i]
		for(j=a.length-1;j>=i+1;j--)
			a.elem[j+1] = a.elem[j]; // 元素后移
		a.elem[i+1]=x; // 插入x
		a.length++;	// 表长加1
		return OK;
	}
} // InsertOrderList

注:

(1) 算法中设置的断言表明以下程序代码正确执行时所要求满足的参数条件,或表明以上程序代码执行后所达到的变量状态;

(2) 在while循环中,条件与&&采用类C的定义,其作用是避免当i<0时,发生数组a.elem越界的错误;

(3) 注意上述算法在a.length=0时也能正确执行;

(4) 可以将上述算法中元素后移的动作并入查找while循环中一起完成。即删去上述算法中的for循环语句,且将while循环语句改为下列形式:

c 复制代码
while(i>=0&&x<a.elem[i]){
	a.elem[i+1]=a.elem[i];
	i--;
}

这里实现该算法时,完全遵照原书中的类型和数据结构,并提供随机初始化,调用stdlib库提供的qsort算法便于测试。

关于为什么要用链表常用的开辟方法来开辟和拓展顺序存储的数组,作者本人一开始也觉得不解,

后来发现不仅可以用链表解决超长数组,还可以用数组来灵活表达链表,具体如何实现,下回分解。

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 123
#define MAX_TEST_ELEM 1000
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 cmp(const void *x,const void *y){
	// qsort函数需要调用的比较函数
	ElemType *a=(ElemType *)x; 
	ElemType *b=(ElemType *)y;
    return (*a-*b);
}

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

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

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 main(){
	ElemType x;
	SqList L;
	if(OK==rand_init_sorted_list(&L)){
		display_list(L);
		
		printf("\nInput an integer x:");
		scanf("%d",&x);
		printf("\nInsert x into list(keep order):\n");
	
		printf("\nInserted elem[%d]=%d\n",InsertOrderSqList(&L,x),x);
		printf("\nAfter insert:\n");
		display_list(L);
		
		if(OK==FreeList_Sq(&L))
			printf("\nFree List success!\n");
	}
	return 0;
}
相关推荐
jiao_mrswang5 分钟前
leetcode-18-四数之和
算法·leetcode·职场和发展
qystca14 分钟前
洛谷 B3637 最长上升子序列 C语言 记忆化搜索->‘正序‘dp
c语言·开发语言·算法
薯条不要番茄酱14 分钟前
数据结构-8.Java. 七大排序算法(中篇)
java·开发语言·数据结构·后端·算法·排序算法·intellij-idea
今天吃饺子19 分钟前
2024年SCI一区最新改进优化算法——四参数自适应生长优化器,MATLAB代码免费获取...
开发语言·算法·matlab
是阿建吖!20 分钟前
【优选算法】二分查找
c++·算法
王燕龙(大卫)24 分钟前
leetcode 数组中第k个最大元素
算法·leetcode
不去幼儿园1 小时前
【MARL】深入理解多智能体近端策略优化(MAPPO)算法与调参
人工智能·python·算法·机器学习·强化学习
Mr_Xuhhh1 小时前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法
盼海2 小时前
排序算法(五)--归并排序
数据结构·算法·排序算法
网易独家音乐人Mike Zhou6 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot