C语言实现数据结构:一.线性表之顺序存储

预备知识

数据结构三要素

1.数据的逻辑结构

逻辑结构是指数据元素之间的逻辑关系,即从逻辑关系上描述数据,分为线性结构非线性结构两大类。
图1-1 数据的逻辑结构分类图

2.数据的存储结构

存储结构是指数据结构在计算机中的表示(又称映像),也称为物理结构。数据的存储结构是逻辑结构用计算机语言的实现。主要有:顺序存储链式存储索引存储散列存储

3.数据的运算

施加在数据上的运算包括运算的定义实现
运算的定义是针对逻辑结构的,指出运算的功能
运算的实现是针对存储结构的,指出运算的具体操作步骤

注: 在专栏中,利用C语言去实现数据结构,实质是去完成表达某种逻辑结构的存储结构,这种实现就是运算的实现,即针对数据的具体操作过程。

线性表

线性表是具有相同数据类型的若干个数据元素的有限序列。其关键操作有:初始化表,按值查找,按位查找,删除,插入,销毁等操作。

正文

顺序表

线性表的顺序存储又称为顺序表,它是用一组地址连续的存储单元,依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也是相邻的。线性表是逻辑结构,而顺序表是其存储结构。

存储描述:

静态分配内存:

const int Maxsize = 100;//定义表格的最大长度 
//ElemType表示存储元素的类型
typedef struct{
	ElemType data[MaxSize];//顺序表中的元素 
	int length;//顺序表的当前长度 
}Sqlist; 

在静态分配内存时,由于数组的大小和空间事先已经固定,一旦空间占满,再加入新的数据将溢出,就会导致程序奔溃。为了解决这个问题,我们可以考虑动态分配内存。例如在第零篇可变数组中就运用了这一思想。

动态分配内存:

const int Initsize = 100//表的初始长度 
typedef struct{
	ElemType *data;//指示动态分配数组的指针 
	int MaxSize,length;//数组的最大容量和当前元素个数 
}Seqlist;

顺序表的基本操作:

以下操作皆以动态分配内存的情况为例
且设定表中元素类型为int

1.创建顺序表

Seqlist seqlist_create(int Initsize){
	Seqlist L;
	L.MaxSize = Initsize;
	L.length = 0;
	L.data = (int*)malloc(sizeof(int)*Initsize);
	return L;
}

2.扩展顺序表

当表中当前元素个数length等于最大容量MaxSize时,再向表中插入元素时则需要扩展顺序表容量。

void seqlist_inflate(Seqlist *L, int more_size){
	//重新开辟一块内存,用作扩展之后的表的空间 
	int *p = (int*)malloc(sizeof(int)*(L->MaxSize + more_size));
	int i;
	for(i=0; i<L->length; ++i)//将表中元素复制到新内存中去 
		p[i] = L->data[i];
	free(L->data);//释放掉旧内存空间 
	L->data = p;
	L->MaxSize += more_size;//更改表的最大容量值 
}

3.插入元素

//将e插入顺序表中第i个位置,即下标i-1处 
int seqlist_insert(Seqlist *L, int i, int e){
	if(i<1 || i>(L->length)+1)//插入的合法位置区间为[1,length+1] 
		return 0;
	if(L->length >= L->MaxSize)//内存空间被用尽,则需要扩展顺序表 
		seqlist_inflate(L, BlockSize);
	int j; 
	for(j=L->length; j>=i; --j)//将第i个元素及之后的元素后移 
		L->data[j] = L->data[j-1];
	L->data[i-1] = e;
	L->length++; 
	return 1;
}

4.删除元素

//删除顺序表中第i个元素 
int seqlist_delete(Seqlist *L, int i, int *e){
	if(i<1 || i>L->length)//判断要删除的位置是否合法 
		return 0;
	int j;
	*e = L->data[i-1];//将被删除的元素记录下来
	for(j=i; j<L->length; ++j)//将i位置之后的所有元素向前移动一位 
		L->data[j-1] = L->data[j];
	L->length--;
	return 1;
} 

5.按值查找

//查询首个元素的值为e的位置 
int seqlist_found_locate(Seqlist *L, int e){
	 int i;
	 for(i=0; i<L->length; ++i){
	 	if(L->data[i] == e)
	 		return i+1;
	 }
	 return 0; //返回0则表示该元素不在表中 
}

6.销毁顺序表

使用完顺序表后,我们需要清空这一段内存空间

void seqlist_free(Seqlist *L){
	free(L->data);
	L->data = NULL;
	L->MaxSize = 0;
	L->length = 0;
} 

可执行程序实例

将上面介绍过的所有操作结合起来,展示一个完整的顺序表程序。

创建一个初始容量MaxSize=5的顺序表,将所有空间填满后,在继续完成添加元素(添加过程中,表格容量继续扩展),删除元素,按值查找等操作。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
const int BlockSize = 5;//每次扩展的长度 

typedef struct{
	int *data;//指示动态分配数组的指针 
	int MaxSize, length;//数组的最大容量和当前元素个数 
} Seqlist;

Seqlist seqlist_create(int Initsize){
	Seqlist L;
	L.MaxSize = Initsize;
	L.length = 0;
	L.data = (int*)malloc(sizeof(int)*Initsize);
	return L;
}

void seqlist_inflate(Seqlist *L, int more_size){
	//重新开辟一块内存,用作扩展之后的表的空间 
	int *p = (int*)malloc(sizeof(int)*(L->MaxSize + more_size));
	int i;
	for(i=0; i<L->length; ++i)//将表中元素复制到新内存中去 
		p[i] = L->data[i];
	free(L->data);//释放掉旧内存空间 
	L->data = p;
	L->MaxSize += more_size;//更改表的最大容量值 
	printf("内存空间不足,扩展完成,当前顺序表最大容量为%d\n", L->MaxSize);
}

//将e插入顺序表中第i个位置,即下标i-1处 
int seqlist_insert(Seqlist *L, int i, int e){
	if(i<1 || i>(L->length)+1)//插入的合法位置区间为[1,length+1] 
		return 0;
	if(L->length >= L->MaxSize)//内存空间被用尽,则需要扩展顺序表 
		seqlist_inflate(L, BlockSize);
	int j; 
	for(j=L->length; j>=i; --j)//将第i个元素及之后的元素后移 
		L->data[j] = L->data[j-1];
	L->data[i-1] = e;
	L->length++; 
	return 1;
}

//删除顺序表中第i个元素 
int seqlist_delete(Seqlist *L, int i, int *e){
	if(i<1 || i>L->length)//判断要删除的位置是否合法 
		return 0;
	int j;
	*e = L->data[i-1];
	for(j=i; j<L->length; ++j)//将i位置之后的所有元素向前移动一位 
		L->data[j-1] = L->data[j];
	L->length--;
	return 1;
} 

//查询首个元素的值为e的位置 
int seqlist_found_locate(Seqlist *L, int e){
	 int i;
	 for(i=0; i<L->length; ++i){
	 	if(L->data[i] == e)
	 		return i+1;
	 }
	 return 0; //返回0则表示该元素不在表中 
} 

void seqlist_free(Seqlist *L){
	free(L->data);
	L->data = NULL;
	L->MaxSize = 0;
	L->length = 0;
} 

int main(int argc, char const *argv[])
{
	int Initsize, flag;
	printf("请输入顺序表的初始最大容量:");
	scanf("%d",&Initsize); 
	Seqlist L = seqlist_create(Initsize);
	int i, num;
	for(i=0; i<L.MaxSize; ++i){
		printf("在第%d位插入数字:", i+1);
		scanf("%d", &num);
		seqlist_insert(&L, i+1, num);
	}
	printf("\n请在任意位置插入元素,输入-1即可停止插入\n");
	int locate;
	while(1){
		printf("输入要插入元素的位置: ");
		scanf("%d", &locate);
		if(locate==-1){
			printf("插入操作终止\n");
			break;
		}
		
		printf("输入第%d个位置要插入的元素:", locate);
		scanf("%d", &num);
		if(seqlist_insert(&L, locate, num))
			printf("插入成功\n");
		else{
			printf("插入失败,请在[1,%d]内插入元素", L.length+1);
		}
	} 
	
	printf("\n进入删除操作,输入-1即可停止删除\n");
	while(1){
		printf("请输入要删除的元素位置:");
		scanf("%d", &locate);
		if(locate==-1){
			printf("删除操作终止\n");
			break;
		}
		int e;
		if(seqlist_delete(&L, locate, &e))
			printf("成功删除第%d位上的元素%d\n", locate, e);
		else{
			printf("删除失败,请在[1,%d]内删除元素", L.length);
		}
	}
	
	printf("\n进入按值查找,当查找的数值不存在顺序表内即终止查询\n");
	printf("请输入要查找的元素值:");
	while(1){
		scanf("%d", &num);
		flag = seqlist_found_locate(&L, num);
		if(!flag){
			printf("%d不存在于顺序表内,查找结束\n", num);
			break;
		}
		else
			printf("%d在顺序表中第%d个位置,查找成功,可输入其他元素值:", num, flag); 
	}
	
	printf("\n所有操作完成,释放顺序表内存空间\n");
	seqlist_free(&L); 
	return 0;
}
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页