——如果代码存在问题,请务必评论告诉我,感激不尽(#^.^#)
——动态和静态的顺序表差别主要在于开辟内存的方式,动态顺序表中的数据所在内存是通过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