线性表的顺序表示及课后习题

最近已经开始了王道单科书的学习,但是学习进度很慢,嘿嘿,开学已经第三周了才更新出来线性表的顺序存储代码,由于线性表的顺序存储之前的文章已经介绍过,在此便不再继续展开介绍。

以下是王道的数据结构线性表顺序存储实现代码课后习题代码,仅供大家参考:

线性表的主要操作和课后习题函数列表
//一般线性表的基本操作 
int InitList(SqList &L);		//初始化线性表 
int Empty(SqList &L);			//线性表判空
void PrintList(SqList &L);		//输出线性表
int Length(SqList L);			//求表长
int DestroyList(SqList &L);				//销毁线性表操作 
int LocateElem(SqList L, ElemType e);			//按值查找操作
ElemType GetElem(SqList L, int i);				//按位查找操作 
int ListInsert(SqList &L, int i, ElemType e);		//插入操作 
int ListDelete(SqList &L, int i, ElemType &e);		//删除操作 

//以下函数为王道课后综合题, 2021版王道《数据结构》 
int DeleteMinValue(SqList &L, ElemType &e);		//课后习题1 
int ReverseList(SqList &L);						//课后习题2
int DeleteSameValue(SqList &L, ElemType x);		//课后习题3->实现方式1 
int DeleteSameValue2(SqList &L, ElemType x);	//课后习题3->实现方式2
int DeteteOrderST(SqList &L, ElemType s, ElemType t);			//课后习题4
int DeleteST(SqList &L, ElemType s, ElemType t); 				//课后习题5
int DeleteSameValue06(SqList &L);								//课后习题6
SqList MergeList(SqList &L1, SqList &L2, SqList &L3);			//课后习题7
void ReverseSqList(SqList &L, int start, int end);		//辅助函数反转线性表中从start至end的元素
void Test09(SqList &L, int m, int n);						//课后习题8
int BinaryFindXIndex(SqList &L, int x);					//辅助函数折半法查找 
int FindXIndex(SqList &L, int x);							//课后习题9
全部实现代码
#include<stdio.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define INFEASIBLE -1
#define OVERFLOW -2
//#define InitSize 100	//表长度的初始定义(动态开辟) 
#define MaxSize 50		//定义线性表的最大长度
typedef int ElemType;		//ElemType类型代替int型 

typedef struct{
    
    				
	ElemType data[MaxSize];		//顺序表的元素 
	int length;					//顺序表的当前长度 
}SqList;						//顺序表的类型定义 

//typedef struct{
    
    
//	ElemType *data;					//指示动态分配数组的指针 
//	int MaxSize, length;		//数组的最大容量和当前指针 
//}SeqList;						//数组分配数组顺序表的类型定义 


//一般线性表的基本操作 
int InitList(SqList &L);		//初始化线性表 
int Empty(SqList &L);			//线性表判空
void PrintList(SqList &L);		//输出线性表
int Length(SqList L);			//求表长
int DestroyList(SqList &L);				//销毁线性表操作 
int LocateElem(SqList L, ElemType e);			//按值查找操作
ElemType GetElem(SqList L, int i);				//按位查找操作 
int ListInsert(SqList &L, int i, ElemType e);		//插入操作 
int ListDelete(SqList &L, int i, ElemType &e);		//删除操作 

//以下函数为王道课后综合题, 2021版王道《数据结构》 
int DeleteMinValue(SqList &L, ElemType &e);		//课后习题1 
int ReverseList(SqList &L);						//课后习题2
int DeleteSameValue(SqList &L, ElemType x);		//课后习题3->实现方式1 
int DeleteSameValue2(SqList &L, ElemType x);	//课后习题3->实现方式2
int DeteteOrderST(SqList &L, ElemType s, ElemType t);			//课后习题4
int DeleteST(SqList &L, ElemType s, ElemType t); 				//课后习题5
int DeleteSameValue06(SqList &L);								//课后习题6
SqList MergeList(SqList &L1, SqList &L2, SqList &L3);			//课后习题7
void ReverseSqList(SqList &L, int start, int end);		//辅助函数反转线性表中从start至end的元素
void Test09(SqList &L, int m, int n);						//课后习题8
int BinaryFindXIndex(SqList &L, int x);					//辅助函数折半法查找 
int FindXIndex(SqList &L, int x);							//课后习题9

int main(){
    
    
	SqList L1;
	InitList(L1);
	for(int i = 0; i < 20; i++)
		ListInsert(L1, L1.length+1, 2*i);
	PrintList(L1);
//	DeleteSameValue06(L);

	FindXIndex(L1, 4);
	PrintList(L1);
	return 0;
}

//初始化线性表 
int InitList(SqList &L){
    
    
	L.length = 0;
}


/**
插入操作 
在顺序表L的第i(1<=i<=L.length+1)个位置插入新元素e 
*/
int ListInsert(SqList &L, int i, ElemType e){
    
    
	if(i < 1 || i > L.length+1)				//判断i的范围是否有效 
		return FALSE;
	if(L.length >= MaxSize)					//当前的存储空间已满,不能再次存储 
		return FALSE;
	
	for(int j = L.length; j >= i; j--)		//将第i个元素及之后的元素依次进行后移 
		L.data[j] = L.data[j-1];
	
	L.data[i-1] = e;			//在第i个位置插入元素e 
	L.length++;					//线性表长度加 1 
	return TRUE; 
}


/**
删除操作
删除顺序表L中第i(1 <= i <= L.length)个位置的元素,并将删除元素的值带回 
*/
int ListDelete(SqList &L, int i, ElemType &e){
    
    
	if(i < 1 || i > L.length)			//判断i的范围是否有效 
		return FALSE;
	
	e = L.data[i-1];			//将被删除元素赋值给 e 
	
	for(int j = i; j < L.length; j++)	//将第i个元素之后的元素依次进行前移 
		L.data[j-1] = L.data[j];
	
	L.length--;				//线性表长度减 1 
	return TRUE;
}


//判空操作 
int Empty(SqList &L){
    
    
	if(L.length <= 0)
		return TRUE;
	else
		return FALSE;
}


/**
按值查找
在顺序表L中查找第一个元素值等于e的元素并返回其位序 
*/
int LocateElem(SqList L, ElemType e){
    
    
	for(int i = 0; i < L.length; i++){
    
    
		if(L.data[i] == e)
			return i+1;			//下标为i元素值等于e,返回其为位序i+1 
	}
	
	return 0;
}


//按位查找操作, 返回表中第i个位置的元素值 
ElemType GetElem(SqList L, int i){
    
    
	if(i < 1 || i > L.length)
		return FALSE;
	else
		return L.data[i-1];
}

//求表长 
int Length(SqList L){
    
    
	return L.length;	
}

//销毁操作,将顺序表清空销毁 
int DestroyList(SqList &L){
    
    
	int e = 0;
	
	while(!Empty(L)){
    
    			//若顺序表不为NULL,进行循环删除操作,直至清空 
		ListDelete(L, 1, e);
	}
	
	return TRUE;
}


//输出操作 
void PrintList(SqList &L){
    
    
	if(Empty(L)){
    
    						//首先判断是否表空 
		printf("该线性表为空表.\n");
		return;
	}
	
	printf("线性表L的所有元素值为:\n");	//输出线性表中所有元素的值 
	for(int i = 0; i < L.length; i++)
		printf("%d\n", L.data[i]);
	printf("输出完毕, 共有 %d 个数据.\n", L.length);
}



/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------
以下函数为王道课后综合题, 2021版王道《数据结构》 
*/

/*
1、 从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值。
空出的位置由最后一个元素填补,若顺序表为空则显示出错信息并退出运行
*/
int DeleteMinValue(SqList &L, ElemType &e){
    
    
	if(Empty(L)){
    
    							//若为空表,则输出错误信息并返回 
		printf("该表为空,删除失败!\n");
		return FALSE;
	}
	
	int min = 0;						//定义min,作为记录线性表最小值的下标,初始化为首元素 
	for(int i = 1; i < L.length; i++){
    
     
		if(L.data[min] > L.data[i])		//通过循环 “打擂台 ”方式进行比较 
			min = i;				// min不断刷新为最小值的下标 
	}
	e = L.data[min];					//记录最小值并待返回 
	L.data[min] = L.data[L.length-1];		//将顺序表的最后一个元素填充至最小值位置,即删除 
	L.length--;							//线性表长度减 1 
	
	return TRUE;
}


/*
2、 设计一个高效的算法,将顺序表L的所有元素逆置,要求算法的空间复杂度为O(1) 
*/
int ReverseList(SqList &L){
    
    
	int temp = 0;				//辅助变量 
	for(int i = 0; i < L.length/2; i++){
    
    
		temp = L.data[i];					//交换L.data[i] 与 L.data[L.length-1-i] 
		L.data[i] = L.data[L.length-1-i];
		L.data[L.length-1-i] = temp;
	}
	
	return OK;
}



/*
3、对长度为n的顺序表L,编写一个时间复杂度为O(n)、空间复杂度为O(1)的算法,该算法删除线性表中所有值为x的数据元素。 
*/
//第一种解法 
int DeleteSameValue(SqList &L, ElemType x){
    
    
	int i = 0, j = 0;				//定义i作为变量遍历原线性表,j作为线性表中不为x的个数 
	for(i = 0; i < L.length; i++){
    
    
		if(L.data[i] != x)			//若线性表中元素不为x 
			L.data[j++] = L.data[i];		//生成不包括x的新线性表 
	}
	
	L.length = j;		//更新 新线性表的长度
	return OK;
}


//第二种解法 
int DeleteSameValue2(SqList &L, ElemType x){
    
    
	int i = 0, k = 0;				//k记录值等于x的元素的个数 
	while(i < L.length){
    
    
		if(L.data[i] == x)
			k++;
		else
			L.data[i-k] = L.data[i];		//当前元素前移k个单位 
		i++;
	}
	
	L.length = L.length - k;			//顺序表L的长度更新 
	return TRUE;
}


/*
4、从有序顺序表中删除其值在给定值s与t之间(要求s<t)的所有元素,如果s或t不合适或顺序表为空,则显示出错信息并退出运行。 
*/
int DeteteOrderST(SqList &L, ElemType s, ElemType t){
    
    
	int i, j ;
	if(s >= t || L.length <= 0){
    
    
		printf("请检查输入参数s、t有误或线性表为空。\n");
		return FALSE;
	}
	for(i = 0; i<L.length && L.data[i] < s; i++);				//寻找值大于等于s的第一个元素 
	if(i >= L.length)
		return FALSE;											//若所有值均小于s则返回 
	for(j = i; j<L.length && L.data[j] <= t; j++);				//寻找值大于t的第一个元素,即最后一个删除元素的下一个元素 
	for(;j < L.length; j++,i++){
    
    
		L.data[i] = L.data[j];						//前移操作,填充被删元素位置 
	}
	
	L.length = i;
	return TRUE;
} 


/*
5、从顺序表中删除其值在给定值s与t之间(包含s和t,要求s<t)的所有元素,如果s或t不合理或顺序表为空,显示出错信息并退出运行 
*/
//该题与第三题非常类似,只是将判断条件稍作改变 
int DeleteST(SqList &L, ElemType s, ElemType t){
    
    
	int i = 0, k = 0;			//i作为线性表遍历下标,k记录值等于值落在s、t之间元素的个数 
	if(s >= t || L.length <= 0){
    
    
		printf("请检查输入参数s、t有误或线性表为空。\n");
		return FALSE;
	}
	while(i < L.length){
    
    
		if(L.data[i]>=s && L.data[i]<=t)		//若k记录值等于值落在s、t之间
			k++;							//记录数累加 
		else
			L.data[i-k] = L.data[i];		//当前元素前移k个单位 
		i++;
	}
	
	L.length = L.length-k;
	return TRUE;
}


/*
6、从有序表中删除所有其值重复的元素,使表中所有元素的值不同 
*/
int DeleteSameValue06(SqList &L){
    
    
	int i = 1, j = 0;
	for(i = 1;i < L.length; i++){
    
    
		if(L.data[j] != L.data[i]){
    
    
			L.data[++j] = L.data[i];			//特别注意,++j和j++含义不同,++j指的是先下标累加再赋值,j++是先赋值再累加 
		}
	}
	L.length = j+1;
	return OK;
}


/*
7、将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表 
*/
SqList MergeList(SqList &L1, SqList &L2, SqList &L3){
    
    
	if(L1.length == 0)							//线性表L1的长度为0 
		return L2;
	if(L2.length == 0)							//线性表L2的长度为0 
		return L1;
	if(L1.length == 0 && L2.length == 0)			//线性表L1和L2的长度均为0 
		return L3;
	int i = 0, j = 0, k = 0;
	while(i < L1.length && j < L2.length){
    
    			//使用while()循环对有序线性表进行合并 
		if(L1.data[i] <= L2.data[j])					//若L1的值比L2的小,将L1元素值添加到L3之上 
			L3.data[k++] = L1.data[i++];				
		else											//若L1的值比L2的大,将L2元素值添加到L3之上 
			L3.data[k++] = L2.data[j++];
	}
	while(i < L1.length) L3.data[k++] = L1.data[i++];		//对剩余的L1、L2线性表进行检索添加 
	while(j < L2.length) L3.data[k++] = L2.data[j++];
	L3.length = k;											//更新线性表的长度 
	return L3;
}



/*
8、已知在一维数组A[m+n]中依次存放两个线性表(a1,a2,a3,...,Am)和(b1,b2,b3,...,Bn),试编写一个函数,将数组中两个顺序表
的位置互换,即将(b1,b2,b3,...,Bn) 放在 (a1,a2,a3,...,Am)的前面 
*/
//作为辅助函数,交换线性表中第start(下标)到end(下标)位置的元素 
void ReverseSqList(SqList &L, int start, int end){
    
    
	if(start >= end)
		return;
	int mid = (start + end)/2, temp = 0;
	while(start <= mid){
    
    						//对start至end之间的元素进行反转 
		temp = L.data[start];
		L.data[start++] = L.data[end];
		L.data[end--] = temp;
	}
	
}
//反转执行操作 
void Test09(SqList &L, int m, int n){
    
    
	ReverseSqList(L, 0, L.length-1);			//首先,逆序整个线性表--->(Bn,...,b2,b1,Am,...,a3,a2,a1) 
	ReverseSqList(L, 0, n-1);					//之后,逆序线性表中前半部分元素(Bn,...,b2,b1)---->(b1,b2,b3,...,Bn)
	ReverseSqList(L, n, n+m-1); 				//最后,逆序线性表中前半部分元素(Am,...,a3,a2,a1)---->(a1,a2,a3,...,Am)
}



/*
9、线性表(a1,a2,a3,...,An)中的元素递增有序且按顺序存储于计算机内。要求设计一个算法,完成用最少时间在表中查找数值为x的元素,
若找到则将其与后继元素位置相交换,若找不到则将其插入表中并使表中元素仍递增有序。 
*/
//作辅助函数折半法查找 
int BinaryFindXIndex(SqList &L, int x){
    
    
	if(L.length == 0)				//异常判断 
		return -1;
	int left = 0, right = L.length-1, mid;			//定义left、right,左右夹击进行折半法查找 
	while(left <= right){
    
    						//left < right时,无法检索到边界的情况 
		mid = (left + right)/2;
		if(L.data[mid] < x)					//当mid小于x时 
			left = mid + 1;						//left指针左移 
		else if(L.data[mid] > x)			//当mid大于x时 
			right = mid - 1;					//right指针右移 
		else
			return mid+1;						//返回查找成功坐标 
	}
	return -1;
}

//问题的主调用函数 
int FindXIndex(SqList &L, int x){
    
    
	int temp = 0, result;
	result = BinaryFindXIndex(L, x);			//折半法查找元素,返回元素位序 
	if(result != -1 && result < L.length){
    
    				//若能够找到,则与其后元素进行交换 
		printf("检索成功,原次序为 %d , 正在与位置为 %d 的数据交换...\n", result, result+1); 
		temp = L.data[result-1];
		L.data[result-1] = L.data[result];
		L.data[result] = temp;
	}
	else											//若找不到该元素,则将该元素插入原有有序顺序表 
	{
    
    
		printf("未检索到查找的数据,正在插入...\n"); 
		int i = 0;
		for(i = 0; x >= L.data[i]; i++);				//查找插入位置 
		ListInsert(L, i+1, x);						//调用插入元素函数 
	}
	return OK;
}

猜你喜欢

转载自blog.csdn.net/weixin_43479947/article/details/115136688
今日推荐