目录
定义
顺序表是存储相同数据元素的有序序列。
顺序表定义分为静态顺序表和动态顺序表:
1)、静态顺序表在定义时就规定了能存储的数据的大小,会造成空间不够或者空间利用率不足的问题
2)、动态顺序表则可很好的避免这个问题
#include<stdio.h>
#include<stdlib.h>
#define N 10
typedef int SLDataType;
静态的顺序表
struct SeqList
{
SLDataType a[N];
int size;
};
//动态的顺序表
typedef struct SeqList
{
SLDataType* a;
int size; //存储的有效数据的个数
int capacity; //容量
}SL;
基本操作
顺序表的初始化
初始化就是给顺序表申请空间,并对初始容量进行定义。用malloc进行动态内存申请。
void SLInit(SL *psl)
{
psl->a = malloc(sizeof(SLDataType)*4);
if (psl->a == NULL)
{
perror("malloc fail");
return;
}
psl->capacity = 4;
psl->size = 0;
}
增加元素
头插法进行元素扩展
在插入前都要对指针进行断言,防止野指针问题,并且在进行插入前要判断当前申请的空间够不够插入,若是不够插入要进行realloc重新申请更大的空间,并将psl->a指向刚才申请的空间,然后更改顺序表的容量。
void SLCheckCapacity(SL* psl)
{
assert(psl);
if (psl->size == psl->capacity)
{
SLDataType* temp = realloc(psl->a, sizeof(SLDataType) * psl->capacity * 2);//扩容到二倍
if (temp == NULL)
{
perror("realloc fail");
return;
}
psl->a = temp;
psl->capacity *= 2;
}
}
头部插入是将元素整体进行后移操作,用循环可解决这个问题,最后将0号位置的元素设置成要插入的元素即可。
void SLPushFront(SL* psl, SLDataType x)
{
assert(psl);
SLCheckCapacity(psl);
int end = psl->size - 1;
while (end >= 0)
{
psl->a[end + 1] = psl->a[end];
end--;
}
psl->a[0] = x;
psl->size++;
}
尾插法进行元素扩展
尾插是将要插入的元素每次插入在顺序表的最后,同样的在插入元素之前要进行assert(psl)断言检查空指针问题,也是要检查顺序表的容量是否够插入元素,不够插入元素就进行扩展。最后将psl->size位置的元素设置为要插入的元素。最后更改psl->size加一。
void SLPushBack(SL* psl, SLDataType x)
{
assert(psl);
SLCheckCapacity(psl);
psl->a[psl->size++] = x;
}
指定位置插入元素
在指定位置插入元素也是元素进行移动,在插入前也是要进行断言,并且要判断插入位置是否合法,检查当前顺序表的容量。
插入的本质就是元素的移动,将pos位置后的元素整体的后移,最后设置pos位置的值为要插入的值然后更改size即可。
void SLInsert(SL* psl, int pos, SLDataType x)
{
/*if (pos<0 || pos>psl->size)
return;*/
assert(psl);
assert(0 <= pos && pos <= psl->size);//其表达式值为假时终止程序
SLCheckCapacity(psl);
/*int end = psl->size;
while (end > pos-1 )
{
psl->a[end] = psl->a[end - 1];
end--;
}
psl->a[pos-1] = x;*/
int end = psl->size - 1;
while (end >= pos)
{
psl->a[end + 1] = psl->a[end];
end--;
}
psl->a[pos] = x;
psl->size++;
}
删除元素
在头部进行删除元素
删除元素的本质也是进行元素的移动,将第一个元素之后的元素整体进行前移并修改size的值即可。
在删除元素之前要进行assert(psl)和assert(psl->size>0)的断言。防止空指针和空顺序表的问题。
void SLPopFront(SL* psl)
{
assert(psl);
/*if (psl->size == 0)
return;*/
/*int i = 0;
for ( i = 0; i < psl->size-1; i++)
{
psl->a[i] = psl->a[i + 1];
}*/
assert(psl->size > 0);
int start = 0;
while (start < psl->size - 1)
{
psl->a[start] = psl->a[start + 1];
start++;
}
psl->size--;
}
在尾部进行删除元素
在删除元素之前要进行assert(psl)和assert(psl->size>0)的断言。防止空指针和空顺序表的问题。
尾删不需要移动元素,只需要修改size的值即可。
void SLPopBack(SL* psl)
{
assert(psl);
//暴力检查
assert(psl->size > 0);
if (psl->size > 0)
psl->size--;
}
删除指定位置元素
删除元素的本质也是进行元素的移动,将要删除元素之后的元素整体进行前移并修改size的值即可。
在删除元素之前要进行assert(psl)和assert(psl->size>0)的断言。防止空指针和空顺序表的问题。
void SLErase(SL* psl, int pos)
{
assert(psl);
assert(0 <= pos && pos < psl->size);//其表达式值为假时终止程序
SLCheckCapacity(psl);
int start = pos;
while (start < psl->size - 1)
{
psl->a[start] = psl->a[start + 1];
start++;
}
psl->size--;
}
改变相应位置元素
顺序表基于数组进行存储,在修改时用下标进行修改即可
void SLModify(SL* psl, int pos, SLDataType x)
{
assert(psl);
assert(0 <= pos && pos < psl->size);
psl->a[pos] = x;
}
查找固定值
查找指定元素的位置,查找成功返回对应元素下标,查找失败返回-1。
int SLFind(SL* psl, SLDataType x)
{
assert(psl);
int i = 0;
for ( i = 0; i < psl->size; i++)
{
if (psl->a[i] == x)
return i;
}
return -1;
}
总结
顺序表的操作都是基于数组进行,只要理解了数组的工作原理,对顺序表的操作就没有问题!