顺序表(动态)的各种基本操作
- 静态顺序表:使用定长数组存储元素。
- 动态顺序表:使用动态开辟的数据存储。
静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表。
优点:
- 支持随机访问。需要随机访问数据时,可以适应很好的算法。
缺点:
- 头部、中部插入插入时间效率低。
- 连续的物理空间,空间不够了以后需要增容:
① 增容有一定层度的消耗。
② 为了避免频繁的增容,一般我们按倍数去增容。
这就导致空间用不完时,会存在空间浪费。
#include <stdio.h>
#include <assert.h>
typedef int SLDataType;
typedef struct SeqList
{
SLDataType *arr; //指向动态开辟的数组
int size; //数组中有效数据个数
int capacity; //容量空间大小
}SList;
void SeqListInit(SList *SL);
void SeqListDestory(SList *SL);
void SeqListPrint(SList *SL);
void SeqListCheckCapacity(SList *SL);
void SeqListPushFront(SList *SL, SLDataType data);
void SeqListPushBack(SList *SL, SLDataType data);
void SeqListInsert(SList *SL, int pos, SLDataType data);
void SeqListPopFront(SList *SL);
void SeqListPopBack(SList *SL);
void SeqListDelete(SList *SL, int pos);
int SeqListFind(SList *SL, SLDataType data);
int main()
{
SList L;
SeqListInit(&L);
for(int i = 0; i <= 5; i++)
{
SeqListPushBack(&L, i);
}
SeqListPrint(&L);
SeqListPushBack(&L, 10);
printf("在尾部插入10:\n");
SeqListPrint(&L);
printf("在位置4处插入60:\n");
SeqListInsert(&L, 4, 60);
SeqListPrint(&L);
printf("查找10\n");
int i = SeqListFind(&L, 10);
if(i != -1)
printf("存在的位置为%d", i);
return 0;
}
//顺序表的初始化
void SeqListInit(SList *SL)
{
SL->arr = NULL;
SL->size = SL->capacity = 0;
}
//顺序表的销毁
void SeqListDestory(SList *SL)
{
free(SL->arr);
SL->arr = NULL;
SL->size = SL->capacity = 0;
}
//顺序表的打印
void SeqListPrint(SList *SL)
{
for(int i = 0; i < SL->size; i++)
{
printf("arr[%d]=%d \n", i, SL->arr[i]);
}
}
//检查空间是否充足
void SeqListCheckCapacity(SList *SL)
{
//空间不够时,进行扩容
if(SL->size == SL->capacity)
{
int newcapacity = SL->capacity == 0 ? 4 : SL->capacity * 2;
SLDataType *tmp = (SLDataType *)realloc(SL->arr, newcapacity * sizeof(SLDataType));
if(tmp == NULL)
{
printf("relloc error\n");
exit(-1);
}
SL->arr = tmp; //扩容了
SL->capacity = newcapacity;
}
}
//头插法
void SeqListPushFront(SList *SL, SLDataType data)
{
SeqListCheckCapacity(SL);
int end = SL->size - 1;
while(end >= 0)
{
SL->arr[end+1] = SL->arr[end];
end--;
}
SL->arr[0] = data;
SL->size++;
}
//尾插法
void SeqListPushBack(SList *SL, SLDataType data)
{
SeqListCheckCapacity(SL);
SL->arr[SL->size] = data;
SL->size++;
}
//在pos位置插入data
void SeqListInsert(SList *SL, int pos, SLDataType data)
{
assert(pos >= 0 && pos <= SL->size);
SeqListCheckCapacity(SL);
int end = SL->size - 1;
while(end >= pos)
{
SL->arr[end+1] = SL->arr[end];
end--;
}
SL->arr[pos] = data;
SL->size++;
}
//表头删
void SeqListPopFront(SList *SL)
{
assert(SL->size > 0);
int begin = 1;
while(begin < SL->size)
{
SL->arr[begin - 1] = SL->arr[begin];
begin--;
}
SL->size--;
}
//表尾删
void SeqListPopBack(SList *SL)
{
//方法1
// assert(SL->size > 0);
// SL->size--;
//方法2
if(SL->size > 0)
{
SL->arr[SL->size - 1] = 0;
SL->size--;
}
}
//pos位置删除data
void SeqListDelete(SList *SL, int pos)
{
assert(pos >= 0 && pos < SL->size);
int begin = pos + 1;
while(begin < SL->size)
{
SL->arr[begin - 1] = SL->arr[begin];
begin++;
}
SL->size--;
}
//查找data
int SeqListFind(SList *SL, SLDataType data)
{
for(int i = 0; i < SL->size; i++)
{
if(SL->arr[i] == data)
{
return i;
}
}
return -1;
}