首页 > 其他分享 >数据结构,(动态)顺序表,C语言实现

数据结构,(动态)顺序表,C语言实现

时间:2024-07-13 19:54:49浏览次数:11  
标签:SqeList 顺序 return int ElemType C语言 printf 数据结构 data

——如果代码存在问题,请务必评论告诉我,感激不尽(#^.^#)

——动态和静态的顺序表差别主要在于开辟内存的方式,动态顺序表中的数据所在内存是通过malloc函数实现的,这也意味着,动态顺序表可以更改存储数据的内存大小,其他的话基本没什么差别

1.数据类型定义  struct ElemType

想要建立顺序表,必须先确定顺序表中数据的类型,我这里用的是struct结构体类型,一般的类型(int,char,float)比较简单,所以我就没用(#^.^#),大家可以根据自己的需要进行修改。

typedef struct ElemType
{//元素类型 
	char name[20];
	int age;
	char sex[10]; 
}ElemType;

2.顺序表类型定义  struct SqeList

动态顺序表和静态顺序表的定义有一定的不同,动态顺序表中数据存放地址是动态开辟的,所以类型是一个ElemType*的指针而不是数组;其次动态顺序表的最大存放个数不是一定的,所以需要定义maxsize来描述。

typedef struct SqeList
{//顺序表 
	ElemType* data;
	int length;
	int maxsize;
}SqeList;

3.顺序表初始化  InitList(&L)

动态和静态顺序表在初始化的不同,归根结底是是顺序表结构上的不同。

void InitList(SqeList* L)
{//初始化 
	L->data=(ElemType*)malloc(INITSIZE*(sizeof(ElemType)));
	assert(L->data!=NULL);
	L->length =0;
	L->maxsize=INITSIZE;
}

4.增加内存空间  IncreaseList(&L)

增加内存空间可以通过malloc或者realloc函数来实现,二者使用起来有些区别,realloc更方便,malloc更直观

malloc扩充内存

void IncreaseList(SqeList* L)
{//增加内存空间 
	ElemType* p=(ElemType*)malloc((L->maxsize+INCREASESIZE)*(sizeof(ElemType)));
	assert(p!=NULL);
	//转移数据 
	int i=0;
	for(i=0;i<L->length;i++)
	{
		p[i]=L->data[i];
	}
	free(L->data);
	L->data=p;
	p=NULL;
	L->maxsize+=INCREASESIZE;
	printf("扩容成功!\n");
}

realloc扩充内存

void IncreaseList(SqeList* L)
{//增加内存空间 
	L->data=realloc(L->data,(L->maxsize+INCREASESIZE)*(sizeof(ElemType)));
	assert(L->data!=NULL);
	L->maxsize+=INCREASESIZE;
	printf("扩容成功!\n");
}

5.在位序i上插入数据ListInsert(&L,i,e)

虽然这里的e不改变他的真实值,可以直接传数据,但由于结构体的空间占用比较大,传地址会更高效,所以只要涉及到结构体,我传的大多数是const型的结构体地址,直接传值也是可以的;值得注意的是,位序是从1开始的,而数组的下标是从0开始的,这一点让我挺头疼的o(╥﹏╥)o

bool ListInsert(SqeList* L,int i,const ElemType* e)
{//在位序i上插入数据 
    if(L->length==L->maxsize)
    {
    	printf("空间已经满了!\n");
    	IncreaseList(L);
	}
	if(i>=1&&i<=(L->length+1))
	{
		int j=0;
		for(j=L->length-1;j>=i;j--)
		{
			L->data[j+1]=L->data[j];
		}
		L->data[i-1]=*e;
		L->length++;
		printf("插入成功!\n");
		return true;
	}
	printf("插入失败!\n");
	return false;
}

 

6.删除位序i上的数据  ListDelete(&L,i,e)

因为是顺序表,我们找到对应位序的数据地址是很容易的,所以一般都是按位删除,当然也可以按值删除,不过稍微麻烦一点(一个一个遍历比较,然后找到第一个相同的数据,然后进行删除)。

bool ListDelete(SqeList* L,int i,ElemType* e)
{//删除位序i上的数据 
	if(i<=0||i>L->length)
	{
		printf("删除失败!\n");
		return false;
	}
	*e=L->data[i-1];
	int j=0;
	for(j=i-1;j<L->length-1;j++)
	{
		L->data[j]=L->data[j+1];
	}
	L->length--;
	return true;
}

 

7.比较数据是否相同  ElemCompare(e1,e2)

由于数据的比较是很常用的,所以我们把他封装出来,这样我们下次用的时候只需要调用就可以了。

int ElemCompare(const ElemType* e1,const ElemType* e2)
{//数据比较,相同返回1,不同返回0 ,不同数据类型的比较方式会不同 
	if(strcmp(e1->name,e2->name)==0&&strcmp(e1->sex,e2->sex)==0&&e1->age==e2->age)
	{
		return 1;
	}
	return 0;
}

 8.查询数据所在的位序  LocateElem(L,e)

int LocateElem(const SqeList* L,const ElemType* e)
{//查找数据,返回位序 
	int i=0;
	for(i=0;i<L->length;i++)
	{
		if(ElemCompare(L->data+i,e)==1)
		{
			return i+1;
		}
	 } 
	return 0;//返回找到元素的位序,0表示不存在 
}

9.单个数据的打印输出  ElemPrint(&L,i)

void ElemPrint(SqeList* L,int i)
{
	printf("%s %d %s \n",L->data[i-1].name,L->data[i-1].age,L->data[i-1].sex);
}

 

10.顺序表的遍历及打印  ListTraverse(L)

如果你想要遍历做别的事情,可以根据需要修改循环里的内容。

void ListTraverse(SqeList* L)
{
	int i=0;
	for(i=1;i<=L->length;i++)
	{
		ElemPrint(L,i);
	}
}

 

11.得到第i个位序上的数据  GetElem(L,int i,&e)

因为我们想要得到数据,所以函数的参数需要有一个ElemType* e 类型的,我们通过将主函数中变量的地址传入到函数中,(求出所需数据),解引用将数据传到主函数里。

bool GetElem(const SqeList* L,int i,ElemType* e)
{//取第i个位序上的数据 
	if(i<1||i>L->length)
	{
		return false;
	}
	else
	{
		*e=L->data[i-1];
		return true;
	}
}

 12.判断是否为空表   ListEmpty(L)

bool ListEmpty(const SqeList* L)
{//判断是否为空表 
	if(L->length==0)
	{
		return true;
	}
	return false;
}

  13.全部代码

#include<stdio.h>
#include<string.h>
#include<stdbool.h>
#include<stdlib.h>
#include<assert.h>
#define INITSIZE 5 
#define MAXSIZE 5
#define INCREASESIZE 2
void menu()
{
	printf("*************************************\n");
	printf("***1.插入数据       2.删除数据*******\n");
	printf("***3.打印数据表     4.查找数据位序***\n");
	printf("***5.按位查找数据   6.初始化数据表***\n");
	printf("***0.退出程序************************\n");
}
typedef struct ElemType
{//元素类型 
	char name[20];
	int age;
	char sex[10]; 
}ElemType;
typedef struct SqeList
{//顺序表 
	ElemType* data;
	int length;
	int maxsize;
}SqeList;
void InitList(SqeList* L)
{//初始化 
	L->data=(ElemType*)malloc(INITSIZE*(sizeof(ElemType)));
	assert(L->data!=NULL);
	L->length =0;
	L->maxsize=INITSIZE;
}
void IncreaseList(SqeList* L)
{//增加内存空间 
	ElemType* p=(ElemType*)malloc((L->maxsize+INCREASESIZE)*(sizeof(ElemType)));
	assert(p!=NULL);
	//转移数据 
	int i=0;
	for(i=0;i<L->length;i++)
	{
		p[i]=L->data[i];
	}
	free(L->data);
	L->data=p;
	p=NULL;
	L->maxsize+=INCREASESIZE;
	printf("扩容成功!\n");
}
//void IncreaseList(SqeList* L)
//{//增加内存空间 
//	L->data=realloc(L->data,(L->maxsize+INCREASESIZE)*(sizeof(ElemType)));
//	assert(L->data!=NULL);
//	L->maxsize+=INCREASESIZE;
//	printf("扩容成功!\n");
//}
bool ListEmpty(const SqeList* L)
{//判断是否为空表 
	if(L->length==0)
	{
		return true;
	}
	return false;
}
int ListLength(const SqeList* L)
{//返回顺序表元素个数 
	return L->length;
}
bool GetElem(const SqeList* L,int i,ElemType* e)
{//取第i个位序上的数据 
	if(i<1||i>L->length)
	{
		return false;
	}
	else
	{
		*e=L->data[i-1];
		return true;
	}
}
int ElemCompare(const ElemType* e1,const ElemType* e2)
{//数据比较,相同返回1,不同返回0 ,不同数据类型的比较方式会不同 
	if(strcmp(e1->name,e2->name)==0&&strcmp(e1->sex,e2->sex)==0&&e1->age==e2->age)
	{
		return 1;
	}
	return 0;
}
int LocateElem(const SqeList* L,const ElemType* e)
{//查找数据,返回位序 
	int i=0;
	for(i=0;i<L->length;i++)
	{
		if(ElemCompare(L->data+i,e)==1)
		{
			return i+1;
		}
	 } 
	return 0;//返回找到元素的位序,0表示不存在 
}
bool ListInsert(SqeList* L,int i,const ElemType* e)
{//在位序i上插入数据 
    if(L->length==L->maxsize)
    {
    	printf("空间已经满了!\n");
    	IncreaseList(L);
	}
	if(i>=1&&i<=(L->length+1))
	{
		int j=0;
		for(j=L->length-1;j>=i;j--)
		{
			L->data[j+1]=L->data[j];
		}
		L->data[i-1]=*e;
		L->length++;
		printf("插入成功!\n");
		return true;
	}
	printf("插入失败!\n");
	return false;
}
bool ListDelete(SqeList* L,int i,ElemType* e)
{//删除位序i上的数据 
	if(i<=0||i>L->length)
	{
		printf("删除失败!\n");
		return false;
	}
	*e=L->data[i-1];
	int j=0;
	for(j=i-1;j<L->length-1;j++)
	{
		L->data[j]=L->data[j+1];
	}
	L->length--;
	return true;
}
void ElemPrint(SqeList* L,int i)
{
	printf("%s %d %s \n",L->data[i-1].name,L->data[i-1].age,L->data[i-1].sex);
}
void ListTraverse(SqeList* L)
{
	int i=0;
	for(i=1;i<=L->length;i++)
	{
		ElemPrint(L,i);
	}
}
int main()
{
	int i=0;
	int input=0;
	SqeList L1;
	ElemType e1;
	InitList(&L1);
	do
	{
		menu();
		printf("选择操作:"); 
		scanf("%d",&input);
		switch(input)
		{
			case 1:
				printf("分别输入插入数据的姓名年龄性别:\n");
		       	scanf("%s%d%s",e1.name,&(e1.age),e1.sex); 
			    ListInsert(&L1,L1.length+1,&e1);
				break;
			case 2:
				printf("输入要删除的数据所在位序:\n");
				scanf("%d",&i);
				ListDelete(&L1,i,&e1);
				printf("删除的数据是:\n");
				printf("%s %d %s \n",e1.name,e1.age,e1.sex);
				break;
			case 3:
				ListTraverse(&L1); 
				break;
			case 4:
				printf("输入要查找的数据:\n");
				scanf("%s%d%s",e1.name,&(e1.age),e1.sex);
				i=LocateElem(&L1,&e1);
				if(i==0)
				{
					printf("没有此数据!\n");
				}
				else
				{
					printf("该数据的位序为:%d\n",i);
				}
				break;
			case 5:
				printf("输入要查找的数据位序:\n");
				scanf("%d",&i);
				GetElem(&L1,i,&e1);
				printf("%d位上的数据为:\n",i);
				printf("%s %d %s\n",e1.name,e1.age,e1.sex);
				break;
			case 6:
				InitList(&L1);
				printf("初始化成功!\n");
				break;
			default:
				printf("选择错误,重新选择\n");
				break;
		}
	}while(input);
	return 0;
 } 

 

标签:SqeList,顺序,return,int,ElemType,C语言,printf,数据结构,data
From: https://blog.csdn.net/2301_81831359/article/details/140404966

相关文章

  • 数据结构与算法学习day4之单向链表
    1.单向链表的的定义链表是有序的列表,这是它在内存中的存储,如下图所示:链表是以节点的形式存储的,是链式存储每个节点都包含两个部分,一个是data域,一个是next域指向下一个节点每个节点不一定是连续存储链表分为带头节点和不带头节点2.单向链表的实现思路(1)添加添加节点的......
  • C语言中关键字volatile
     1:什么是volatile?    在C语言中,volatile关键字同样用于修饰变量,volatile告诉编译器该变量的值可能会在程序的控制之外被改变,因此编译器在优化代码时不能对该变量的访问进行优化,比如不能将其缓存到寄存器中,而是每次访问时都需要直接从内存中读取其值。2:变量的访问......
  • 数据结构(队列的实现)
    目录队列队列的定义队列的实现创建队列的结构队列的初始化进行插入数据删除数据计算个数 判断是否为空返回队列头部数据返回队列尾部数据队列队列的定义队列是:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First......
  • C语言——数组、sizeof关键字
    一、数组1.数组的引入与定义: C语言中的数组是一种基本的数据结构,用于在计算机内存中连续存储相同类型的数据。数组中的每个元素可以通过索引来访问,索引通常是一个整数,用于指定元素在数组中的位置。在C语言中,数组索引是从0开始的。 要使用数组,必须在程序中先定义数组,即通知......
  • C语言内存管理深度解析
    第一章基础概念梳理1.1堆与栈的区别在C语言中,堆和栈是两种重要的内存管理机制,它们之间存在显著的区别。首先,栈内存是由编译器自动分配和释放的,其操作方式类似于数据结构中的栈,遵循后进先出(LIFO)的原则。每当一个函数调用发生时,就会在栈上分配一块内存用于存储该函数的局部变......
  • C语言菜鸟学习(函数)
    引入C语言本身就是由多个函数模块组成,在C语言本身自带的头文件中,也有很多被封装好的函数,在初学C语言时,我们最先使用的就是使用printf()函数输出一个“helloworld”;而printf()函数就是被封装在#include<stdio.h>头文件中的。但是经过封装的函数我们无法看到源代码,在实际开发中......
  • 震惊!!!居然有这么详细的顺序表 ,走过路过不要错过
     一.顺序表顺序表(SequentialList)是一种线性表,其元素在内存中连续存放,可通过索引直接访问。线性表在逻辑结构上是线性结构,也就是说是连续的一条直线,但是在物理结构上并不一定是连续的。线性表在物理结构上存储时,通常是以数组和链式结构的形式存储的。顺序表是一种基础的数......
  • C语言——练习:水仙花数、n次幂值的计算
    1.输入一个数判断是否是水仙花数,并输出100—999之间所有的水仙花数水仙花数(Narcissisticnumber),也被称为超完全数字不变数(pluperfectdigitalinvariant,PPDI)、自恋数、自幂数、阿姆斯壮数或阿姆斯特朗数(Armstrongnumber),是指一个N位正整数(N≥3),它的每个位上的数字的N次幂之和......
  • 第八篇:Python集合:高效的无序集数据结构
    1.集合的定义Python中的集合(set)是一种高度优化的无序且不重复的数据结构。它在概念上类似于数学中的集合,能够存储多个不同的元素。集合的这种特性使其成为处理唯一性和成员资格检查的理想选择。在Python中,我们可以通过两种主要方式定义集合:a)使用花括号{}:set1={1,......
  • 在VSCODE中创建C语言环境,编译、运行、调试。
    1、安装MinGWMinGW-w64-for32and64bitWindowsdownload|SourceForge.net下载下来是一个压缩包对压缩包解压得到文件夹mingw64将文件夹mingw64剪切到C:\ProgramFiles目录下配置环境变量点击系统变量里面的Path将C:\ProgramFiles\mingw64\bin目录添加......