一、基本概念
概念:用一组地址连续的存储单元依次存储线性表的数据元素即顺序存储结构。
特点:逻辑上相邻的数据元素,物理次序上也相邻。
顺序表分为静态顺序表和动态顺序表,且在生活中常用的也是动态顺序表。这是因为静态顺序表提前开辟空间可能会导致空间开辟过多或空间不足的情况,而动态顺序表则会避免这个问题。
顺序表的主要实现的就是对数据的增删查改。
二、重难解析
malloc函数:指针名 = (指针类型*)malloc(sizeof(指针类型)*数据数量)
realloc函数:指针名=(数据类型*)realloc(要改变内存大小的指针名,(大小)*sizeof(数据类型))
1.动态分配----扩容
对于一个空间已满的动态顺序表来说要对该顺序表扩容就要通过reallon函数
int newcapacity=ps->capacity==0?4:ps->capacity*2;
ElemType *tmp=(ElemType*)realloc(ps->a,newcapacity*sizeof(ElemType));
上面第一行代码中运用了多目运算符如果空间为0的话newcapacity=4;若空间已满则newcapacity=capacity*2 即原空间扩大两倍。
而第二行代码则是开辟一块空间。
2.头插
(1)检查空间是否足够
(2)要将原顺序表中所有元素后移
(3)将x赋值给下标为0的ps->a
(4)ps->size++
void slpushfront(sqlist *ps, ElemType x)
{
slcheckcapacity(ps);
int end=ps->size-1;
while(end>=0){
ps->a[end+1]=ps->a[end];
end--;
}
ps->a[0]=x;
ps->size++;
}
3.尾插
对于动态顺序表来说尾插法相对简单,只需判断空间是否足够即可。
然后ps->a中尾部下标变为ps->size,再将x赋值给ps->a即可。
最后ps->size++。
void slpushback(sqlist*ps,ElemType x)
{
slcheckcapacity(ps);
ps->a[ps->size]=x;
ps->size++;
}
4.删除
删除算法就是要把删除位置往后的元素往前移并覆盖要删除的位置,顺序表长度-1。
void slerase(sqlist *ps, int pos)
{
int begin=pos+1;
while(begin<ps->size){
ps->a[begin-1]=ps->a[begin];
begin++;
}
ps->size--;
以上就是本人在学习顺序表过程中感觉比较难的地方。
三、完整代码
下面附上动态顺序表的完整代码
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
typedef int status;
typedef int ElemType;
typedef struct {
ElemType *a; //指向动态数组指针
int size ; //数据个数
int capacity; //容量-空间大小
}sqlist;
//初始化
void slInit(sqlist *ps)
{
ps->a=NULL;
ps->size=ps->capacity=0;
}
//检查容量-扩容
void slcheckcapacity(sqlist *ps)
{
if(ps->size==ps->capacity){
int newcapacity=ps->capacity==0?4:ps->capacity*2;//如果空间为0则扩容可放置4个元素的空间,如果已满则在原基础上增加1倍
ElemType *tmp=(ElemType*)realloc(ps->a,newcapacity*sizeof(ElemType));
if(tmp==NULL)
{
perror("relloc:");
exit(-1); //结束程序
}
ps->a=tmp;
ps->capacity=newcapacity;
}
}
//尾插
void slpushback(sqlist*ps,ElemType x){
slcheckcapacity(ps);
ps->a[ps->size]=x;
ps->size++;
}
//打印
void slprint(sqlist *ps)
{
for(int i=0;i<ps->size;i++){
printf("%d ",ps->a[i]);
}
printf("\n");
}
//销毁-防止内存泄露
int sldestory(sqlist *ps){
if(ps->a)
{
free(ps->a);
ps->a=NULL;
ps->size=ps->capacity=0;
}
return OK;
}
//头插
void slpushfront(sqlist *ps, ElemType x){
slcheckcapacity(ps);
int end=ps->size-1;
while(end>=0){
ps->a[end+1]=ps->a[end];
end--;
}
ps->a[0]=x;
ps->size++;
}
//任意插入
int slInsert(sqlist*ps,int pos,ElemType x){
if (pos<0 || pos>ps->size)/*判断插入位置是否越界*/
{
return ERROR;
}
if (ps->size == ps->capacity)/*判断是否有插入空间*/
{
slcheckcapacity(ps);
}
for (int j = ps->size - 1; j >= pos; j--)
{
ps->a[j + 1] = ps->a[j];/*从后向前遍历,并把元素后移直到pos的位置*/
}
ps->a[pos] = x;/*把x插入线性表中*/
ps->size += 1;/*因为是插入操作,线性表长度加1*/
return OK;
}
//删除
void slerase(sqlist *ps, int pos){
int begin=pos+1;
while(begin<ps->size){
ps->a[begin-1]=ps->a[begin];
begin++;
}
ps->size--;
}
//查找
int slfind(sqlist *ps,int pos,ElemType x){
if (pos<0 || pos>ps->size)/*判断查找位置是否越界*/
{
return ERROR;
}
for(int i=0;i<=ps->size;i++){
if(ps->a[i]==x){
return i;
}
}
return -1;
}
//修改
int slmodify(sqlist*ps,int pos,ElemType x){
if (pos<0 || pos>ps->size)/*判断修改位置是否越界*/
{
return ERROR;
}
ps->a[pos]=x;
return OK;
}