系列文章目录
数据结构之顺序表
一、顺序表的介绍
1.1 概念
定义:顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储,在数组上完成数据的增删查改。
在存储方式上有静态存储和动态存储
1.2 工作机制
以动态存储为例
增加元素
删除元素
查找元素
更改元素
———————————————————————————————
二、顺序表的实现
采用的编译器:VS2022
Seqlist.h
#pragma once
//创建一个线性表
//逻辑结构 - 线性结构
//存储结构 - 顺序结构
//之后用到的头文件
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
//宏定义
#define DEFAULT_INT 10//数组初始化默认大小
#define ADD_INT 10//每次增容大小
//重命名数据类型,以方便之后改变存储的元素类型
//(假如想存储浮点形数据,就只用将下面的int改为float,省去了麻烦)
typedef int SLDateType;
//动态顺序表
typedef struct SeqList
{
SLDateType *date;
size_t size;//存储的数据个数
size_t capacity;//能存储的数据最大个数
}SL;
//接口函数
void SeqListInit(SL* ps);//初始化 :开辟空间
void SeqListDestroy(SL* ps);//销毁:归还空间
void SeqListprint(SL* ps);//打印数组
//4大基础功能
//1. 增加功能
void SeqListPushBack(SL *ps, SLDateType x);//尾插
void SeqListPushFront(SL* ps, SLDateType x);//头插
void SeqListInsert(SL* ps, size_t pos, SLDateType x);//指定插
//2. 删除功能
void SeqListPopBack(SL* ps);//尾删
void SeqListPopFront(SL* ps);//头删
void SeqListErase(SL* ps, size_t pos);//指定删
//3. 查找功能
int SeqListFind(SL* ps, SLDateType x);
//4. 更改功能
void SeqListChange(SL* ps, SLDateType x, int pos);
//扩容 - 辅助功能
void CheckCapacity(SL* ps);
Seqlist.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Seqlist.h"
//初始化
void SeqListInit(SL* ps)
{
//开辟动态内存空间
ps->date = (SLDateType*)calloc(DEFAULT_INT, sizeof(SLDateType));
assert(ps->date);
ps->size = 0;
ps->capacity = DEFAULT_INT;
}
//增加功能
//1.尾插
void SeqListPushBack(SL* ps, SLDateType x)
{
assert(ps);
CheckCapacity(ps);//检查容量
ps->date[ps->size] = x;
ps->size++;
}
//2.头插
void SeqListPushFront(SL* ps, SLDateType x)
{
assert(ps);
CheckCapacity(ps);
//往后移
int end = ps->size - 1;
while (end >= 0)
{
ps->date[end + 1] = ps->date[end];
end--;
}
ps->date[0] = x;
ps->size++;
}
//3.随机插
void SeqListInsert(SL* ps, size_t pos, SLDateType x)
{
assert(pos >= 1 && pos <= ps->size + 1);
CheckCapacity(ps);
int end = ps->size - 1;
while (end >= pos - 1)
{
ps->date[end + 1] = ps->date[end];
end--;
}
ps->date[pos - 1] = x;
ps->size++;
}
//删除功能
//1.尾删
void SeqListPopBack(SL* ps)
{
if (ps->size == 0)
{
return;
}
ps->size--;
}
//2.头删
void SeqListPopFront(SL* ps)
{
int i = 0;
for (i = 0; i < ps->size - 1; i++)
{
ps->date[i] = ps->date[i + 1];
}
ps->size--;
}
//3.随机删
void SeqListErase(SL* ps, size_t pos)
{
assert(pos >= 1 && pos <= ps->size + 1);
int begin = pos - 1;
while (begin <= ps->size)
{
ps->date[begin] = ps->date[begin + 1];
begin++;
}
ps->size--;
}
//查找功能
int SeqListFind(SL* ps, SLDateType x)
{
assert(ps);
int pos = 0;
for (pos = 0; pos < ps->size; pos++)
{
if (ps->date[pos] == x) {
printf("找到了,下标为%d\n", pos);
return pos;
}
}
printf("未找到\n");
}
//更改功能
void SeqListChange(SL* ps, SLDateType x, int pos)
{
assert(ps);
if (ps->size >= pos + 1) {
printf("更改成功\n");
ps->date[pos] = x;
}
else {
printf("pos超过范围\n");
}
}
//销毁
void SeqListDestroy(SL* ps)
{
free(ps->date);
ps->date = NULL;
ps->capacity = 0;
ps->size = 0;
}
//打印
void SeqListprint(SL* ps)
{
int i = 0;
for (i = 0; i < ps->size; i++)
{
printf("%d ", ps->date[i]);
}
}
//检查容量
void CheckCapacity(SL* ps)
{
//扩容
if (ps->capacity == ps->size - 1)
{
SLDateType *tmp = (SLDateType*)realloc(ps->date,
(ps->capacity + ADD_INT) * sizeof(SLDateType));
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
else
{
printf("realloc succee\n");
ps->capacity += ADD_INT;
ps->date = tmp;
}
}
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Seqlist.h"
//测试接口函数
void TestSeqList(SL* s1)
{
SeqListInit(s1);
SeqListPushBack(s1, 1);
SeqListPushBack(s1, 2);
SeqListPushBack(s1, 3);
SeqListPushBack(s1, 4);
SeqListPushBack(s1, 5);
SeqListFind(s1, 4);
SeqListChange(s1, 9, 3);
SeqListInsert(s1, 6, 9);
SeqListErase(s1, 3);
SeqListprint(s1);
SeqListDestroy(s1);
}
int main(void)
{
SL a = { 0 };
TestSeqList(&a);
return 0;
}
——————————————————————————————————————————
三、顺序表的优缺点
顺序表的优点
1 )无须增加额外的存储空间表示结点间的逻辑关
系。
2 )可以方便地随机存取表中任一结点。
顺序表的缺点:
1 )插入和删除运算不方便,通常须移动大量结
点,效率较低。
2 )难以进行连续的存储空间的预分配,尤其是当表变
化较大时。