您的当前位置:首页数据结构之顺序表的实现

数据结构之顺序表的实现

2022-03-11 来源:爱问旅游网
数据结构之顺序表的实现

数据结构之顺序表的实现

⼀、原理

1.定义

顺序表是在计算机中以数组形式保存的。

2.特点

在计算机中占⽤连续的⼀段内存⼀旦声明,空间⼤⼩⼀般不变

⼆、初始化相关操作

包括:

1. 结构体的定义2. 顺序表的创建3. 顺序表清空

4. 判断顺序表是否为空

1.结构体定义

即定⼀个满⾜顺序表定义的结构体,其中包含 数组、存储长度、总长度。

typedef int ElemType; //将int抽象为ElemType,表明顺序表也可以存储其他类型(如将int改为char)struct List{

ElemType *list;

//声明数组⽤于给顺序表存储数据,等价于以下声明⽅式 //ElemType[] list;

int length; //⽤于记录顺序表存储的数据长度

int MaxSize; //⽤于记录顺序表最⼤长度(即最多存储数据)}

2.初始化

对顺序表进⾏初始化,包括分配⾃定义长度的数组空间,设定存储长度为0,存储长度为规定值

//初始化,传⼊需要初始化的顺序表和初始化长度void InitList(struct List *L,int maxSize){ //初始化长度合法性判断 if(maxSize<0){

printf(\"初始化长度⾮法!\\n\"); exit(1); //退出程序 }

//对顺序表长度进⾏赋值 L->MaxSize = maxSize;

//根据初始化长度和存储数据类型来动态分配数组 L->list = malloc(sizeof(maxSize*sizeof(ElemType))); //分配成功判定 if(!L->list){

printf(\"动态分配存储失败\\n\"); exit(1); }

//初始化存储数据为0个 L->length = 0;}

3.清空

将顺序表内容清空,⽤于某些题⽬要求或节省空间

//清空,传⼊需要清空的顺序表void ClearList(struct List *L){

//判断顺序表是否已经为空 if(L->list!=NULL){

free(L->list); //释放顺序表中数组内存 L->list = 0; L->length = 0; L->MaxSize = 0; }}

4. 判断是否为空

判断顺序表是否为空,在某些操作之前,先要判断顺序表是否为空,防⽌出错

int isEmpty(struct List *L){

return L->length==0?1:0; //顺序表最⼤长度为0则为空返回1,否则返回0}

三、增加相关操作

包括:

1. 向表头插⼊元素x2. 向表尾插⼊元素x

3. 向第n个位置插⼊元素x

4. 向递增的线性表中插⼊元素x,之后仍然保持有序

进⾏操作之前,还需要⼀个⽅法,当插⼊元素超过数组长度时,将数组容量扩⼤,即重新申请空间

Tip:将顺序表扩⼤⼀倍空间

void ReMalloc(struct List *L){

ElemType *p = realloc(L->list,2*L->MaxSize*sizeof(ElemType)); if(!p){

printf(\"空间分配失败\\n\"); exit(1); }

L->list = p; //使list重新指向新⽣成的空间 L->MaxSize = 2*L->MaxSize;

printf(\"存储空间已经扩⼤为2倍\\n\");}

1.向表头插⼊元素x

void insertElemToHead(struct List *L,ElemType x){ int i;

//判断存储空间是否已满 if(L->length==L->MaxSize){

printf(\"存储空间已满,重新分配中...\"); ReMalloc(L); }

//所有元素后移

for(i=L->length;i>0;i--){ L->list[i+1]=L->list[i]; }

L->list[i]=x; L->length++;}

2.向表尾插⼊元素x

void insertElemToTail(struct List *L,ElemType x){ //判断存储空间是否已满 if(L->length==L->MaxSize){

printf(\"存储空间已满,重新分配中...\"); ReMalloc(L); }

L->list[L->length++]=x;}

3.向线性表L的第n个位置插⼊元素x

void insertElemSomewhere(struct List *L,ElemType x,int n){ //判断存储空间是否已满 if(L->length==L->MaxSize){

printf(\"存储空间已满,重新分配中...\");

ReMalloc(L); } int i;

for(i=L->length;i>=n;i--){ L->list[i] = L->list[i-1]; }

L->list[i] = x; L->length--;}

四、删除相关操作

包括:

1. 删除表头元素并返回被删除的值2. 删除第n个元素并返回被删除元素3. 从线性表L中删除值为X的第⼀个元素

1.删除表头元素并返回被删除的值

删除表头第⼀个元素,长度减少1,返回被删除的值

ElemType delHeadElem(struct List *L){ ElemType x = L->list[0]; //合法性判断 if(L->length==0){

printf(\"线性表为空,不能删除\\n\"); exit(1); }

for(int i=0;ilength;i++){ L->list[i] = L->list[i+1]; }

L->length--; return x;}

2.删除第n个元素并返回被删除元素

ElemType delSomeElem(struct List *L,int n){ if(nlength){

printf(\"n位置越界,不能删除\"); exit(1); }

ElemType x = L->list[n-1]; for(int i=n;ilength;i++){ L->list[i]=L->list[i+1]; }

L->length--; retur x;}

3.从线性表L中删除值为X的第⼀个元素

从线性表L中删除值为X的第⼀个元素,若删除成功则返回1,否则返回0

int delElemKnown(struct List *L,ElemType x){ int i,j;

//先找出值为X的下标 for(i=0;ilength;i++){ if(L->list[i]==x){ break; } }

for(j=i;ilength;j++){ L->list[j]=L->list[j+1]; }

L->length--; return 1;}

五、修改相关操作

包括:

1. 把线性表中第n个元素修改为x

1.把线性表中第n个元素修改为x

把线性表中第n个元素修改为x,若成功则返回1,失败返回0

int updateElemKnown(struct List *L,ElemType x,int n){ if(n>L->length||n<1){ return 0; }

L->list[n]=x; return 1;}

六、查找相关操作

包括:

1. 查找第n个位置的值2. 顺序遍历输出所有值3. 返回值等于x的下标

1.查找第n个位置的值

输⼊要查找的坐标,若合法则范围对应的值,若⾮法则提⽰并推出

int getElem(struct List *L,int n){ if(n<0||n>L->MaxSize){

printf(\"查找位置超出长度!\\n\"); exit(1); }

return L->list[n-1]; //n-1的原因是查找的第n个是从1开始计数,⽽数组是从0开始计数}

2.顺序遍历输出所有值

输出顺序表中的所有值

void getAll(struct List *L){ int i = 0;

while(ilength){ printf(L->list[i]+\"\\"); i++; }

printf(\"\\n\");}

3.查找值为x的节点并返回其坐标

输⼊要查找的值x,若存在则范围⾸次出现的下标,否则返回0

void findElem(struct List *L,ElemType x){ int i;

for(i=0;ilength;i++){ if(L->list[i]==x){ return i; } }}

七、总结

1.优点

查找⽅便空间利⽤率⾼

2.缺点

删除和增加操作效率低

空间固定,不易扩展

⼋、完整代码

#include \"stdio.h\"#include /**

* =======顺序表的定义========= */

typedef int ElemType;//结构体定义struct List{

ElemType *list;//存储数据 int length;//存储长度 int MaxSize;//最⼤长度};

//初始化

void initList(struct List *L,int maxSize){ //初始化长度合法性判断 if(maxSize<0){

printf(\"初始化长度⾮法!\\n\"); exit(1); //退出程序 }

L->MaxSize = maxSize;

L->list = malloc(sizeof(maxSize* sizeof(ElemType))); //判断分配空间是否成功 if(!L->list){

printf(\"空间分配失败\"); exit(1); }

L->length=0;}

//清空

void clearList(struct List *L){ if(L->list!=NULL){ free(L->list); L->list=0;

L->MaxSize=0; L->length=0; }}

//判空

int isEmpty(struct List *L){ return L->length==0?1:0;}

/**

* =======增加操作========= */

//空间再分配

void reMalloc(struct List *L){

ElemType *p = realloc(L->list,2*L->MaxSize* sizeof(ElemType)); if(!p){

printf(\"空间分配失败\"); exit(1); }

L->list = p;

L->MaxSize = 2*L->MaxSize; printf(\"空间已扩⼤两倍\");}

//向表头插⼊元素

void insertElemToHead(struct List *L,ElemType x){ if(L->length==L->MaxSize){ reMalloc(L);

printf(\"空间已满,重新分配中\"); }

for(int i=L->length;i>0;i++){ L->list[i-1] = L->list[i]; }

L->list[0] = x; L->length++;}

//向表尾插⼊元素

void insertElemToTail(struct List *L,ElemType x){ if(L->length==L->MaxSize){ reMalloc(L);

printf(\"空间已满,重新分配中\"); }

L->list[L->length++] = x;}

//向线性表L的第n个位置插⼊元素x

void insertElemSomewhere(struct List *L,ElemType x,int n){ int i;

if(L->length==L->MaxSize){ reMalloc(L);

printf(\"空间已满,重新分配中\"); }

for(i=L->length;i>=n;i--){ L->list[i]=L->list[i-1]; }

L->list[i]=x; L->length++;}

/**

* =======删除操作========= */

//删除表头元素并返回被删除的值void delHeadElem(struct List *L){ ElemType x = L->list[0]; if(L->length==0){

printf(\"顺序表为空,删除失败!\"); exit(1); }

for(int i=1;ilength;i++){ L->list[i-1] = L->list[i]; }

L->length--;}

//删除第n个元素并返回被删除元素

ElemType delSomeElem(struct List *L,int n){ ElemType x = L->list[n-1]; if(n>L->length){

printf(\"n位置越界,不能删除\"); exit(1); }

for(int i=n;ilength;i++){ L->list[i-1] = L->list[i]; }

L->length--; return x;}

//从线性表L中删除值为X的第⼀个元素

int delElemKnown(struct List *L,ElemType x){ int i,j;

for(i=0;ilength;i++){ if(L->list[i]==x){ break; } }

for(j=i;jlength;j++){ L->list[j]=L->list[j+1]; }

L->length--; return 1;}

/**

* =======修改操作========= */

//把线性表中第n个元素修改为x

int updateElemKnown(struct List *L,ElemType x,int n){ if(n>L->length||n<1){ return 0; }

L->list[n]=x; return 1;}

/**

* =======查找操作========= */

//查找第n个位置的值

int getElem(struct List *L,int n){ if(n<0||n>L->MaxSize){

printf(\"查找位置超出长度!\\n\");

exit(1); }

return L->list[n-1]; //n-1的原因是查找的第n个是从1开始计数,⽽数组是从0开始计数 }

//顺序遍历输出所有值 void getAll(struct List *L){ int i = 0;

while(ilength){

printf(\"%d\\ i++; }

printf(\"\\n\"); }

//查找值为x的节点并返回其坐标

int findElem(struct List *L,ElemType x){ int i;

for(i=0;ilength;i++){ if(L->list[i]==x){ return i; } }}

//主函数int main(){

//初始化操作测试 struct List L; initList(&L,20); //插⼊操作测试

insertElemToHead(&L,2);

insertElemSomewhere(&L,4,2); insertElemToTail(&L,5); printf(\"%d\\n\ printf(\"%d\\n\ //删除操作测试

delElemKnown(&L,2); printf(\"%d\\n\ //修改操作测试

updateElemKnown(&L,8,1); //查找操作测试

printf(\"%d\\n\ printf(\"%d\\n\ printf(\"%d\\n\ getAll(&L);}

因篇幅问题不能全部显示,请点此查看更多更全内容