【线性表】顺序表及其基本运算和应用

顺序存储结构的c语言描述
#define MAXSIZE 100/*此处的宏定义常量表示线性表可能达到的最大长度*/
typedef struct{
     
	ElemType elem[MAXSIZE];/*线性表占用的数组空间*/
	int last;/*记录线性表中最后一个元素在数组elem[]中的位置(下标值),
	空表置为-1*/ 
}SeqList; 

在C语言数据结构中,关于数据元素的类型定义均用“ ElemType e;”来表示,其中e是表示数据元素的变量,而ElemType则是它的类型,ElemType的含义就是“数据元素的类型”,是一个抽象的概念,是表示我们所要使用的数据元素应有的类型。
ElemType是数据结构上为了说明问题而用的一个词。它是element type(“元素的类型”)的简化体。因为数据结构是讨论抽象的数据结构和算法,一种结构中元素的类型不一定是整型、字符型、浮点型或者用户自定义类型,为了不重复说明,使用过程用 “elemtype” 代表所有可能的数据类型,简单明了的概括整体。
在算法中,除特别说明外,规定ElemType的默认是int型。

顺序表的基本运算
一、按值查找
int Locate(SeqList L ,ElemType e)
/*在顺序表L中依次存放着线性表中的元素,
在表中查找到与e相等的元素,
若L[i]=e则找到该元素,并返回i的数值
若找不到,则返回“-1”*/
{
     
	i=0;/*i为扫描计数器,初始值为0,即从第一个元素开始比较*/
	while((i<L.last)&&(L.elem[i]!=e)){
     
		i++;/*顺序扫描表,直到找到值为e的元素或扫描到表尾而没找到*/
	} 
	if(i<=L.last)
	return (i+1);/*若找到,则返回其序号*/ 
	else
	return (-1);/*若没找到,则返回空序号*/ 
 } 
二、插入

其实是移动部分的代码

int InsList(SeqList *L,int i,ElemType e)
/*在顺序表L中第i个元素之前插入一个元素e
表长n=L->last+1,
i的合法取值范围是1<=i<=L
{
     
	int k;
	if((i<1)||(i>L->last+2))/*首先判断插入位置是否合法*/
	{
     
		printf("插入位置i值不合法");
		return (ERROR);
	} 
	if(L->last>=maxsize-1)
	{
     
		printf("表已满无法插入");
		return (ERROR);	
	}
	for(k=L->last;k>=i-1;k--)/*为插入元素而移动位置*/
	{
     
		L->elem[k+1]=L->elem[k];
	}
	L->elem[i-1]=e;/*在c语言中,第i个元素的下标为i-1*/
	L->last++;
	return (OK);
 } 
三、删除
#include
int Locate(SeqList *L ,int i,ElemType *e)
/*在顺序表L中删除第i个数据,并用指针参数e返回其值
i的合法取值为1<=i<=L.last+1*/
{
     
	int k;
	while((i<1)||(i>L->last+1)) {
     
		printf("删除位置不合法!");
		return(error);
	}
	*e=L->elem[i-1]/*将删除的元素存放到e所指的变量中*/
	for(k=i; k<=L->last; k++) {
     
		L->elem[k-1]=L->elem[k];
		/*将后面的元素依次前移*/
		L->last--;
		return (ok);
	}
}
四、有序表合并
void merge(SeqList *LA,SeqList *LB,SeqList *LC) {
     
	int i,j,k,l;
	i=0;
	j=0;
	k=0;/*LC 为空表,设LC表的指示器k=0.
设两个指示器 i,j 分别指向表 LA 和 LB 的当前位置,初值均为 0*/
	while(i<=LA->last&&j<=LB->last) {
     
		if(LA->elem[i]<=LB->elem[j]) {
     
			LC->elem[k]=LA->elem[i];
			i++;
			k++;
		} else {
     
			LC->elem[k]=LB->elem[j];
			j++;
			k++;
		}
	}/*:LA 表和 LB 表的当前元素比较,小的元素进 LC 表,且该表的指
示器和 LC 表的指示器 k 均加 1 移向下一个位置。如此下去,直到 LA 或 LB 表
中一个表处理完毕为止。*/
	while(i<=LA->last) {
      /*当表LA比表LB长时,则将表LA余下的元素赋给表LC*/
		LC->elem[k]=LA->elem[i];
		i++;
		k++;
	}
	while(i<=LA->last) {
      /*当表LB比表LA长时,则将表LB余下的元素赋给表LC*/
		LC->elem[k]=LB->elem[j];
		j++;
		k++;
	}
	LC->last=LA->last+LB->last+1;

}
算法应用示例
分解顺序表为奇偶两部分

已知顺序表 L 中的数据元素类型为 int。设计算法将其调整为左右两部分,左边的元素(即排在前面的)均为奇数,右边所有元素(即排在后面的)均为偶数,并要求算法的时间复杂度为 O(n),空间复杂度为 O(1)。

【问题分析】
初见此题,可能会想到额外申请 1 个顺序表空间,之后依次从顺序表 L 中选
择奇数放入新表前部分,选择偶数放在新表的后半部分。但是题目要求空间复杂度为 O(1),很显然上述方法是不可行的。既然要求空间复杂度为 O(1),说明只能借助 1 个辅助空间。

分析题目要求,其实只需要将位于表左半部分的偶数与位于表右半部分的奇数通过一个辅助变量进行交换即可,为此可以设置两个位置指示器 i 和 j,i 初值为 0,j 初值为 L->last。
当L->elem[i]为偶数,L->elem[j]为奇数时,则将 L->elem[i] 与 L->elem[j]交换;否则,L->elem[i]为奇数,i++, L->elem[j]为偶数,j++。这样既可以保证算法的时间复杂度为 O(n),亦可保证空间复杂度为 O(1)。
【算法描述】

adjustsqlist(seqlist *l){
     
	int i=0,j=l->last,t;
	while(i<j){
     
		while(l->elem[i]%2!=0)/*从表的左半部分开始检测,若为奇数,则 i 加 1,直到找到偶数为止*/
		i++;
		while(l->elem[j]%2==0)/*从表的左半部分开始检测,若为偶数,则 j 减 1,直到找到奇数为止*/
		j--;
		if(i<j){
     
			t=l->elem[i];
			l->elem[i]=l->elem[j];
			l->elem[j]=t;
		} 
	}
}

你可能感兴趣的:(数据结构)