赞
踩
一.简介:
顺序表是C语言中的一种数据结构,它通常基于数组实现。顺序表允许我们在连续内存区域上保存线性数据,并且支持快速的随机访问。
通常情况下,顺序表具有以下特点:
*长度固定:一旦创建,其长度就不可以改变。
*支持随机访问:我们可以使用下标(索引)获取指定位置的元素。
*适合静态数据存储:对于只需要在运行时读取而无需修改的数据集合,如静态配置信息等,使用 顺序表非常方便和高效。
由于顺序表在内部实现上通常是一个数组,在进行插入、删除等操作时可能需要进行大量的数据移动,因此,对于需要频繁地增删数据的情况,顺序表性能会受到影响。此时,链表可能更适合用来存储和操作动态数据。后续会再跟新链表的基本操作。
二.顺序表的定义与基本操作
值得注意的是,由于我们使用的是c语言,所以预处理需要做一些处理,比如我们需要以下头文件
代码如下:
- #include<stdio.h>
- #include<stdlib.h>
- #include<stdbool.h>
其中有了#include<stdlib.h>,我们才可以malloc和free
有了#include<stdbool.h>,我们才可以使用bool
我将介绍一下顺序表的结构体定义,顺序表的静态存储与动态存储,并基于动态存储解释顺序表的基本操作。以下是我将介绍的基本操作的函数声明,结尾我会放入完整代码。(过程如有错误,请指出,虚心学习,学无止境!)
代码如下:
- void InitList(SeqList* L);
- void DestroyList(SeqList* L);
- int GetElem(SeqList L,int i);
- int LocateElem(SeqList L,int e);
- bool ListInsert(SeqList* L,int i,int e);
- bool ListDelete(SeqList* L,int i,int* e);
- void IncreaseSize(SeqList* L,int len);
- bool Empty(SeqList L);
- void PrintList(SeqList);
- int Length(SeqList L);
1.实现顺序表的结构体定义:
顺序表的静态存储结构体定义:
代码如下:
- #define Maxsize 10
-
- typedef struct {
- int data[Maxsize];
- int length;
- } SqList;
-
- SqList L;
-
以上为顺序表的静态存储,通常我们更倾向于使用顺序表的动态存储,因为动态存储在顺序表的容量不够时可以增加容量,而静态存储在定义的那一刻就已经固定了容量,无法再更改。
顺序表的动态存储结构体定义:
代码如下:
- typedef struct
- {
- int* data;
- int length;
- int maxsize;
- }SeqList;
由于动态存储更广泛使用,所以接下来的基本操作基于顺序表的动态存储来进行解释说明。
2.初始化
代码如下:
- void InitList(SeqList* L)
- {
- L->data=(int*)malloc(sizeof(int)*Maxsize);
- L->length=0;
- L->maxsize=Maxsize;
- }
3.销毁
代码如下:
- void DestroyList(SeqList* L)
- {
- free(L->data);
- L->data=NULL;
- L->length=0;
- L->maxsize=0;
- }
4.查找
查找分为两种,一种是通过给定的位序得到顺序表中该位置的数据,一种是通过给定的数据得到顺序表中该数据的位置,注意不要混淆。此外,读者还要明白位序和顺序表中下标的区别,位序是从1开始算起,而顺序表中的下标是从0开始算起,要分辨清楚哦。
第一种:通过给定位序查找表中元素
代码如下:
- int GetElem(SeqList L,int i)
- {
- if(i<1||i>L.length)
- return 0;
- return L.data[i-1];
- }
给定的位序如果是小于1或者大于表长,那便是无效数据,返回0;
反之,则返回表中数据,注意返回的是i-1,理由开头解释过了。
同时,为什么这个函数我们是用的int类型而不是bool类型呢?因为我们要返回的数据类型是int
我们开始的定义中,Elemtype(定义的数据类型)为int,为了返回数据,我们的函数定义为int,如果没有返回数据,也即失败了,我们便返回0,返回0的意思便是返回失败。
第二种:通过给定值查找表中等于该值的数据的位置
代码如下:
- int LocateElem(SeqList L,int e)
- {
- for(int i=0;i<L.length;i++)
- {
- if(L.data[i]==e)
- return i+1;
- }
- return 0;
- }
我们通过遍历,直到遍历到元素中的数据的值为给定的数据值,直接返回i+1,也即该元素在表中的下标+1,返回的是位序,否则的话没有相应元素,我们返回0代表返回失败。
同时我们要注意,在for循环里定义i这个操作是c99才可以使用的操作,如果是非c99,我们在外面定义int i,再把i放到for循环里令i=0即可。
5.插入
插入操作我们不但要注意位序和下标的区别,
同时还要留意:插入的时候,是从表尾开始各个元素往后移动一位;删除的时候,是从删除位置开始各个元素往前移动一位。这是一个小细节。
代码如下:
- bool ListInsert(SeqList* L,int i,int e)
- {
- if(i<1||i<L->length+1)
- return false;
- if(L->length>=L->maxsize)
- return false;
- for(int j=L->length;j>=i;j--)
- L->data[j]=L->data[j-1];
- L->data[i-1]=e;
- L->length++;
- return true;
- }
如果给定的位序小于零或者大于表长+1,则返回false。
这里为什么是表长+1呢?是因为我们在进行插入操作的时候,插入之后的位置我们都是要往后移动的,表尾一样要往后移动一位,此时表长+1。
同时,如果此时表长超过了表的最大容量的话,我们没有多余容量再进行插入操作,此时的情况也是false。如果上述的情况都不是的话,则我们可以进行遍历来将表中的元素从表尾开始往后移动一位,具体操作便是将前一个元素赋值给后一个元素。
接着便是插入位置赋值e,表长+1,返回true。
6.删除
代码如下:
- bool ListDelete(SeqList* L,int i,int* e)
- {
- if(i<1||i>L->length)
- return false;
- *e=L->data[i-1];
- for(int j=i;j<L->length;j++)
- L->data[j-1]=L->data[j];
- L->length--;
- return true;
- }
这里无需length+1,要注意的是e是返回删除的元素值,所以这里的e是传入的int*类型
7.扩容
代码如下:
- void IncreaseSize(SeqList* L,int len)
- {
- int* p=L->data;
- L->data=(int*)malloc(sizeof(int)*(len+L->maxsize));
- for(int i=0;i<L->length;i++)
- L->data[i]=p[i];
- L->maxsize+=len;
- free(p);
- }
通过定义指针p指向L->data,旨在保存原有的数据。
然后对L->data重新动态分配得到扩容后的内存空间。
接着通过遍历赋值原有的数据并修改表的最大容量。
最后注意要释放指针p的内存空间。
8.判空
代码如下:
- bool Empty(SeqList L)
- {
- return (L.length==0);
- }
代码效果等同于:
- bool Empty(SeqList L)
- {
- if (L.length==0)
- return true;
- else
- return false;
- }
9.遍历输出
代码如下:
- void PrintList(SeqList L)
- {
- for(int i=0;i<L.length;i++)
- printf("L.data[%d]=%d\n",i,L.data[i]);
- }
10.返回表长
代码如下:
- int Length(SeqList L)
- {
- return L.length;
- }
三.完整代码
代码如下:
- #include<stdio.h>
- #include<stdlib.h>
- #include<stdbool.h>
- #define Maxsize 10
-
- typedef struct
- {
- int* data;
- int length;
- int maxsize;
- }SeqList;
-
- void InitList(SeqList* L);
- void DestroyList(SeqList* L);
- int GetElem(SeqList L,int i);
- int LocateElem(SeqList L,int e);
- bool ListInsert(SeqList* L,int i,int e);
- bool ListDelete(SeqList* L,int i,int* e);
- void IncreaseSize(SeqList* L,int len);
- bool Empty(SeqList L);
- void PrintList(SeqList);
- int Length(SeqList L);
-
- int main()
- {
- return 0;
- }
-
- void InitList(SeqList* L)
- {
- L->data=(int*)malloc(sizeof(int)*Maxsize);
- L->length=0;
- L->maxsize=Maxsize;
- }
-
- void DestroyList(SeqList* L)
- {
- free(L->data);
- L->data=NULL;
- L->length=0;
- L->maxsize=0;
- }
-
- int GetElem(SeqList L,int i)
- {
- if(i<1||i>L.length)
- return 0;
- return L.data[i-1];
- }
-
- int LocateElem(SeqList L,int e)
- {
- for(int i=0;i<L.length;i++)
- {
- if(L.data[i]==e)
- return i+1;
- }
- return 0;
- }
-
- bool ListInsert(SeqList* L,int i,int e)
- {
- if(i<1||i<L->length+1)
- return false;
- if(L->length>=L->maxsize)
- return false;
- for(int j=L->length;j>=i;j--)
- L->data[j]=L->data[j-1];
- L->data[i-1]=e;
- L->length++;
- return true;
- }
-
- bool ListDelete(SeqList* L,int i,int* e)
- {
- if(i<1||i>L->length)
- return false;
- *e=L->data[i-1];
- for(int j=i;j<L->length;j++)
- L->data[j-1]=L->data[j];
- L->length--;
- return true;
- }
-
- void IncreaseSize(SeqList* L,int len)
- {
- int* p=L->data;
- L->data=(int*)malloc(sizeof(int)*(len+L->maxsize));
- for(int i=0;i<L->length;i++)
- L->data[i]=p[i];
- L->maxsize+=len;
- free(p);
- }
-
- bool Empty(SeqList L)
- {
- return (L.length==0);
- }
-
- void PrintList(SeqList L)
- {
- for(int i=0;i<L.length;i++)
- printf("L.data[%d]=%d\n",i,L.data[i]);
- }
-
- int Length(SeqList L)
- {
- return L.length;
- }
-
作者也是考研生,会陆续更新接下来数据结构的代码内容,希望能给广大考研生提供帮助,如有错误,欢迎指出,一起进步!纯手打干货,写文章不易,喜欢的点赞,觉得有用的收藏,点个关注,大家的点赞、收藏、关注便是作者持续更新分享的动力!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。