顺序表在数据结构中一种很重要的逻辑结构 ,它是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。也就是说,顺序表本质是一个数组,它的存储的数据从左向右必须是连续的。
顺序表的结构:
下面这种结构不是顺序表,因为数据不是连续的,5和6中间空了一块空间。
顺序表可以分为:
#define N 100
typedef int SLDataType;
typedef struct SeqList
{
SLDataType array[N]; // 定长数组,数组的大小是固定的,所以是静态储存
size_t size; // 有效数据的个数
}SeqList;
,
1.在头部或中间插入数据需要挪动数据
2.动态增容有增容时有性能的消耗
3增容时一般是以2倍或1.5倍增长的,势必会有一定的空间的浪费,例如,当前最大容量为100,满了以后,增容到200,我在插入5个数据,后面就有95个空间浪费掉了.
在写代码之前,我们先来聊一下写这个增删查改的意义.增删查改的结构随处可见,无论是我们的微信的通讯录里,还是在学校的教务系统里,都需要有一个增删查改去去添加联系人(学生)的信息,查找联系人(学生)的信息,所以学习增删查改的基本结构的对我们的意义很大,当我们学会了增删查改的基本逻辑以后,我们才能去延伸去写通讯录,去写教务系统.或者看懂代码.
静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表。
typedef struct SeqList
{
int* s;
int capacity;//该数组的最大容量
int sz;//该数组当前存储数据的个数
}SeqList;
void SeqListInit(SeqList* pc)
{
pc->s = NULL;
pc->capacity = 0;
pc->sz = 0;
}
如果想在4后面插入一个5,此时的sz为4,只要再pc->s[pc->sz]插入一个5即可,因为5的位置为数组下标为4
的位置.
当然,我们在插入数据之前,得检查是否需要增容.
所以我们在定义一个增容的函数
void CheckCapacity(SeqList* pc)
{
assert(pc);
if (pc->capacity == pc->sz)//若sz等于最大容量,则需要增容
{
pc->capacity = pc->capacity == 0 ? 5 : pc->capacity * 2;
pc->s = (int *)realloc(pc->s, sizeof(int) * pc->capacity);
if (pc->s == NULL)
{
return;
}
printf("增容成功\n");
}
}
void SeqListPushBack(SeqList* pc,int x)
{
assert(pc);//防止pc为NULL
CheckCapacity(pc);//检查是否需要增容
pc->s[pc->sz] = x;
pc->sz++;
}
我们如何把一个数据插入在顺序表的首位置呢?
这就需要我们把数据全部往后移,然后空出首位置的,在把值插入到首位置
代码如下:
void SeqListPushFront(SeqList* pc, int x)
{
assert(pc);//防止pc为NULL
CheckCapacity(pc);//检查是否需要增容
int i = pc->sz;
while (i--)
{
pc->s[i + 1] = pc->s[i];
}
pc->s[0] = x;
pc->sz++;
}
尾删其实很简单,只需要把有效数据减少一个就行,也就是把sz就可以,
参考如下代码;
void SeqListPopFront(SeqList* pc)
{
assert(pc);
pc->s[pc->sz - 1] = 0;
pc->sz--;
}
void SeqListPopFront(SeqList* pc)
{
assert(pc);
if (pc->sz == 0)//当sz=0,也就是说没有有效数据,后面不用删除数据
{
return;
}
for (int i = 0; i < pc->sz - 1; i++)
{
pc->s[i] = pc->s[i + 1];
}
pc->sz--;
}
查找函数是查找想要的数在顺序表中第一个位置,该代码如下
int SeqListFind(SeqList* pc, int x)
{
assert(pc);
for (int i = 0; i < pc->sz; i++)//先阅历一遍数组
{
if (pc->s[i] == x)
{
return i ;//找到了该数,则返回该数在线性表的下标
}
}
return 0;//如果找不到,则返回0
}
代码如下
void SeqListInster(SeqList* pc, int pos, int x)
{
assert(pc);
assert(pos >= 0 && pos < pc->sz);//检查该位置是否为合理
CheckCapacity(pc);//检查容量是否满了
int i = pc->sz-1;
while (i>=pos)
{
pc->s[i + 1] = pc->s[i];
i--;
}
pc->s[pos] = x;
pc->sz++;
}
void SeqListErase(SeqList* pc, int pos)
{
assert(pc);
assert(pos >= 0 && pos < pc->sz);//检查pos是否为有效位置
if (pc->sz == 0)
{
return 0;
}
int i = pos;
for (i = pos; i < pc->sz - 1; i++)
{
pc->s[i] = pc->s[i + 1];
}
pc->sz--;//有效数据减1
}
一、简介 本设计为硬币图像识别统计装置通过数码相机获取平铺无重叠堆积的硬币的...
git工作区,暂存区,版本库之间的关系: 我们建立的项目文件夹就是工作区,在初...
本文实例讲述了jsp中page指令用法。分享给大家供大家参考。具体如下: 一、JSP ...
从功能测试、性能测试、界面测试、安全性测试、易用性、兼容性测试、震动测试七...
首先给扑克牌中每张牌设定一个编号,下面算法实现的编号规则如下: u 红桃按照从...
前言 关于Window,你了解多少呢?看看下面这些问题你都能答上来吗。 如果你遇到这...
大家好,今天我们来简单的聊一聊缓存问题。什么是缓存呢?它在系统设计中是在一个...
我们知道微软将会在今年给Windows10更换全新设计的UI,让Windows10的界面更加整...
今日国内领先的智能数据服务运营商觉非科技完成近亿元A轮融资。本轮融资由和高资...
一、MVC MVC模式的意思是,软件可以分成三个部分。 视图(View):用户界面。 控...