目录
一、顺序表的基本概念
二、顺序表的定义和基本算法
动态顺序表
基本算法
⭕整体前移
⭕整体后移
⭕遍历查找
三、顺序表的接口函数和实现
⭕初始化顺序表:malloc出3个字节的空间
⭕增容检查:每次插入数据都要检查是否sz和capacity相等,若相等就追加2个字节的空间
⭕打印顺序表数据
⭕头插:在sl->data[0]处插入数据,需要数据整体后移
⭕头删:删除sl->data[0]处的数据,需要数据整体前移
⭕尾插:在sl->data[sl->sz]处插入数据
⭕尾删:删除sl->data[sl->sz]处的数据
⭕在指定位置插入数据
⭕删除指定位置的数据
⭕顺序表的销毁
四、总结
SeqList.c
SeqList.h
①线性表:线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...
②顺序表:由物理地址连续的存储单元构成,一般情况下采用数组存储。顺序表是线性表的一种。
⭕基本算法:整体前移、后移和遍历查找。
增:包括头插、尾插和指定位置插入数据,其中头插和指定位置插入数据运用整体后移
删:包括头删、尾删和删除指定位置数据,其中头删和删除指定位置数据运用整体前移
查:运用遍历查找
改:运用遍历查找
由于顺序表中存储的数据是相同类型的,所以我们将其类型定义为SLDataType,这样方便修改顺序表数据类型。
data定义成指针,用C语言中的动态开辟函数在堆区开辟一块空间,data中保存这些空间的第一块空间的地址;
capacity表示这块空间的总容量;
sz表示已存储数据的个数。
⭕整体前移
for (i = pos; i < right - 1; i++)
{
sl->data[i] = sl->data[i + 1];
}
⭕整体后移
for (i = right; i >= pos; i--)
{
sl->data[i+1] = sl->data[i];
}
⭕遍历查找
for(i=0;i<=right;i++)
{
if(sl->data[i]==x)
{
return i;
}
}
⭕初始化顺序表:malloc出3个字节的空间
#define Default_sz 3
void InitSL(SList* sl)
{
assert(sl);
sl->data = (SList*)malloc(Default_sz * sizeof(SList));
sl->capacity = Default_sz;
sl->sz = 0;
}
⭕增容检查:每次插入数据都要检查是否sz和capacity相等,若相等就追加2个字节的空间
int check_capacity(SList* sl)
{
if (sl->capacity == sl->sz)
{
SList* tmp = (SList*)realloc(sl->data, (sl->capacity + 2) * sizeof(SList));
if (tmp == NULL)
{
perror("realloc");
return 0;//增容失败
}
else
{
sl->data = tmp;
sl->capacity += 2;
return 1;
}
}
return 1;
}
⭕打印顺序表数据
void SL_print(const SList* sl)
{
int i = 0;
for (i = 0; i < sl->sz; i++)
{
printf("%d ", sl->data[i]);
}
}
⭕头插:在sl->data[0]处插入数据,需要数据整体后移
void SL_pushfront(SList* sl,SLDataType x)
{
assert(sl);
if (0 == check_capacity(sl))
{
printf("顺序表容量已满\n");
return;
}
int i = 0;
//整体后移
for (i = sl->sz; i >= 0; i--)
{
sl->data[i+1] = sl->data[i];
}
sl->data[0] = x;
sl->sz++;
}
⭕头删:删除sl->data[0]处的数据,需要数据整体前移
void SL_popfront(SList* sl)
{
assert(sl);
if (sl->sz == 0)
{
printf("顺序表无数据\n");
return;
}
int i = 0;
//整体前移
for (i = 0; i < sl->sz - 1; i++)
{
sl->data[i] = sl->data[i + 1];
}
sl->sz--;
}
⭕尾插:在sl->data[sl->sz]处插入数据
void SL_pushback(SList* sl,SLDataType x)
{
if (0 == check_capacity(sl))
{
printf("容量满\n");
return;
}
sl->data[sl->sz] = x;
sl->sz++;
}
⭕尾删:删除sl->data[sl->sz]处的数据
void SL_popback(SList* sl)
{
assert(sl);
if (sl->sz == 0)
{
printf("顺序表无数据\n");
return;
}
sl->sz--;
}
⭕查找
int SL_search(SList* sl, SLDataType x)
{
assert(sl);
if (sl->sz == 0)
{
printf("顺序表无数据\n");
return 0;
}
int i = 0;
for (i = 0; i < sl->sz; i++)
{
if (sl->data[i] == x)
{
return i;
}
}
return 0;//找不到
}
⭕在指定位置插入数据
void SL_insert(SList* sl, SLDataType x, SLDataType pos)
{
assert(pos >=0 && pos<=sl->sz);
if (0 == check_capacity(sl))
{
printf("顺序表容量已满\n");
return;
}
int i = 0;
//sl->data[pos]到sl->data[sl->sz]的数据整体后移
for (i = sl->sz; i >= pos; i--)
{
sl->data[i + 1] = sl->data[i];
}
sl->data[pos] = x;
sl->sz++;
}
⭕删除指定位置的数据
void SL_erase(SList* sl, SLDataType pos)
{
assert(pos >=0 && pos<=sl->sz);
if (sl->sz == 0)
{
printf("顺序表无数据\n");
return;
}
int i = 0;
for (i = pos; i < sl->sz-1; i++)
{
sl->data[i] = sl->data[i + 1];
}
sl->sz--;
}
⭕顺序表的销毁
void SL_destroy(SList* sl)
{
sl->capacity = sl->sz = 0;
free(sl->data);
sl->data = NULL;
}
⭕修改任意位置的数据
void SL_change(SList* sl, SLDataType x,int pos)
{
assert(sl);
sl->data[pos] = x;
}
改:时间复杂度为O(1)
由于顺序表使用数组实现的,所以顺序表访问效率高,访问任意下标的数据时间复杂度为O(1)
增:时间复杂度为O(n)
删:时间复杂度为O(n)
查:时间复杂度为O(n)
顺序表的查找、插入和删除的效率相对低,时间复杂度都是O(n) ,其中尾插和尾删是最好的情况,时间复杂度为O(1)
顺序表的代码全部整理在这里了:
SeqList.c
#include"SeqList.h"
//初始化顺序表
void InitSL(SList* sl)
{
assert(sl);
sl->data = (SList*)malloc(Default_sz * sizeof(SList));
sl->capacity = Default_sz;
sl->sz = 0;
}
//增容检查
int check_capacity(SList* sl)
{
if (sl->capacity == sl->sz)
{
SList* tmp = (SList*)realloc(sl->data, (sl->capacity + 2) * sizeof(SList));
if (tmp == NULL)
{
perror("realloc");
return 0;
}
else
{
sl->data = tmp;
sl->capacity += 2;
return 1;
}
}
return 1;
}
//尾插
void SL_pushback(SList* sl,SLDataType x)
{
if (0 == check_capacity(sl))
{
printf("容量满\n");
return;
}
sl->data[sl->sz] = x;
sl->sz++;
}
//尾删
void SL_popback(SList* sl)
{
assert(sl);
if (sl->sz == 0)
{
printf("顺序表无数据\n");
return;
}
sl->sz--;
}
//头删
void SL_popfront(SList* sl)
{
assert(sl);
if (sl->sz == 0)
{
printf("顺序表无数据\n");
return;
}
int i = 0;
//整体前移
for (i = 0; i < sl->sz - 1; i++)
{
sl->data[i] = sl->data[i + 1];
}
sl->sz--;
}
//头插
void SL_pushfront(SList* sl,SLDataType x)
{
assert(sl);
if (0 == check_capacity(sl))
{
printf("顺序表容量已满\n");
return;
}
int i = 0;
//整体后移
for (i = sl->sz; i >= 0; i--)
{
sl->data[i+1] = sl->data[i];
}
sl->data[0] = x;
sl->sz++;
}
//查找
int SL_search(SList* sl, SLDataType x)
{
assert(sl);
if (sl->sz == 0)
{
printf("顺序表无数据\n");
return 0;
}
int i = 0;
for (i = 0; i < sl->sz; i++)
{
if (sl->data[i] == x)
{
return i;
}
}
return 0;//找不到
}
//指定位置插入数据
void SL_insert(SList* sl, SLDataType x, int pos)
{
assert(pos >=0 && pos<=sl->sz);
if (0 == check_capacity(sl))
{
printf("顺序表容量已满\n");
return;
}
int i = 0;
//sl->data[pos]到sl->data[sl->sz]的数据整体后移
for (i = sl->sz; i >= pos; i--)
{
sl->data[i + 1] = sl->data[i];
}
sl->data[pos] = x;
sl->sz++;
}
//指定位置删除数据
void SL_erase(SList* sl, int pos)
{
assert(pos >=0 && pos<=sl->sz);
if (sl->sz == 0)
{
printf("顺序表无数据\n");
return;
}
int i = 0;
for (i = pos; i < sl->sz-1; i++)
{
sl->data[i] = sl->data[i + 1];
}
sl->sz--;
}
//修改指定位置的数据
void SL_change(SList* sl, SLDataType x,int pos)
{
assert(sl);
if (sl->sz == 0)
{
printf("顺序表无数据\n");
return;
}
sl->data[pos] = x;
}
//打印信息
void SL_print(const SList* sl)
{
int i = 0;
for (i = 0; i < sl->sz; i++)
{
printf("%d ", sl->data[i]);
}
}
//销毁顺序表
void SL_destroy(SList* sl)
{
sl->capacity = sl->sz = 0;
free(sl->data);
sl->data = NULL;
}
SeqList.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
#define Default_sz 3
typedef int SLDataType;
typedef struct SeqList
{
SLDataType* data;
int capacity;
int sz;
}SList;
//初始化
void InitSL(SList* sl);
//打印
void SL_print(const SList* sl);
//尾插
void SL_pushback(SList* sl,SLDataType x);
//尾删
void SL_popback(SList* sl);
//头插
void SL_pushfront(SList* sl,SLDataType x);
//头删
void SL_popfront(SList* sl);
//查找
int SL_search(SList* sl, SLDataType x);
//指定位置插入数据
void SL_insert(SList* sl, SLDataType x, int pos);
//指定位置删除数据
void SL_erase(SList* sl, int pos);
//修改指定位置的数据
void SL_change(SList* sl, SLDataType x, int pos);
//销毁顺序表
void SL_destroy(SList* sl);