顺序表的实现【数据结构】
创始人
2024-11-14 09:37:49
0

1.线性表

线性表(linear list)是n个具有相同特性的数据元素的有线序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表有:顺序表、链表、栈、队列、字符串…
线性表在逻辑上是线性结构,也就是说是连续的一条线。但是在物理结构上并不一定是连续的,比如链表。
线性表在物理上存储时,通常以数组和链式结构的形式存储。

2.顺序表

顺序表

2.1 概念及结构

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
顺序表一般可以分为静态顺序表和动态顺序表
静态顺序表
使用定长数组存储元素。

#define MAX 7 typedef int Datatype;//为了适用不同类型的顺序表 typedef struct SeqList { 	Daratype a[MAX]; 	int sz;//有效数据个数 }SL; 

静态顺序表

动态顺序表
使用动态开辟的数组存储

typedef int Datatype;//为了适用不同类型的顺序表 typedef struct SeqList { 	Daratype* a; 	int sz;//有效数据个数 	int capacity;//存储空间大小 }SL; 

动态顺序表

3.模拟实现

静态顺序表只适合于确定知道要存储多少数据的场景下。在储存空间不确定的场景下,对于静态顺序表当MAX开大了就会造成浪费,当MAX开小了又不够。所以在实际的场景中基本都是使用动态顺序表,根据需要动态分配空间大小。
下面是模拟实现:

3.1 准备工作

定义一个结构体

typedef int Datatype;//为了适用不同类型的顺序表 typedef struct SeqList { 	Datatype* a; 	int sz;//有效数据个数 	int capacity;//存储空间大小 }SL; 

3.2 顺序表的初始化与销毁

对于顺序表的初始化,我的话会先给顺序表开好3个空间的大小.
注意:一定要传地址。

void InitSeqlist(SL* ps) { 	ps->a = (Datatype*)malloc(sizeof(Datatype)*3); 	if(ps->a == NULL)//扩容失败,直接退出程序 	{ 		perror("InitSeqlist"); 		exit(-1); 	} 	ps->sz = 0; 	ps->capacity = 3; } 

销毁
销毁我们直接free就可以了,任何其他值赋0.

void DestorySeqlist(SL* ps) { 	free(ps->a); 	ps->a = NULL; 	ps->sz = 0; 	ps->capacity = 0;	 } 

3.3 顺序表的尾插

插入前我们一定要先检查一下ps是不是应该空指针。
检查完ps后,对于数据的插入会存在两种情况:
1.顺序表已满,需要扩容
2.顺序表未,满直接插入
因为后面的头插与在特定位置的数据插入都会用到检查顺序是否已满,满就扩容的功能,那么我们可以封装成应该函数。

void SeqlistCapacity(SL* ps) { 	if(ps->capacity == ps->sz)//满了 	{ 		Datatype* tmp = (Datatype*)realloc(ps->a, sizeof(Datatype) * 2*ps->capacity); 		if(tmp == NULL)//开辟失败 		{ 			perror("realloc"); 			exit(-1); 		} 		ps->a = tmp; 		ps->capacity *= 2; 	} }    void PushBack(SL* ps,Datatype x) { 	assert(ps); 	//检查空间是否已满 	SeqlistCapacity(ps); 	ps->a[ps->sz] = x; 	ps->sz+=1; } 

3.4 顺序表的尾删

删除前我们一定要先检查一下ps是不是应该空指针。
同时还要删除该顺序表中的数据也又两种情况:
1.顺序表中的数据已经删完了,无法再删。
2.顺序表中的数据足够删除。直接删

void PopBack(SL* ps) { 	assert(ps); 	if(ps->sz>0) 	{ 		ps->sz-=1; 	} } 

3.5顺序表的打印

直接打印就好了

void PrintSeqlist(SL* ps) { 	for (int i = 0; i < ps->sz; ++i) 	{ 		printf("%d ", ps->a[i]); 	} } 

3.6 顺序表的头插

只要是插入数据就需要检查空间是否已满。
然后头插需要移动数据,我们需要把所有的数据都相后移动一位
这样的话,覆盖的顺序就很重要了,如果从前向后覆盖话,有效数据就没了
前

这样的话2就被覆盖了。
后

这样就不会了,还是不明白的话多画图就可以搞懂了。

void PushFront(SL* ps,Datatype x) { 	assert(ps); 	SeqlistCapacity(ps); 	for(int i = ps->sz;i>=1;--i) 	{ 		ps->a[i] = ps->a[i-1]; 	} 	ps->a[0] = x; 	ps->sz += 1; } 

3.7 顺序表的头删

只要是删除就需要判断顺序表是否为空。
这个图我就不画了,大家可以画一画从前面开始覆盖和从后面开始覆盖的图。就会豁然开朗的。

void PopFront(SL* ps) { 	assert(ps); 	assert(ps->sz!=0); 	for(int i = 0;isz-1;++i) 	{ 		ps->a[i] = ps->a[i+1]; 	} 	ps->sz -= 1;  } 

3.8 顺序表查找

遍历顺序表,没找到的话就返回-1

int FindSeqlist(SL* ps,Datatype x) { 	assert(ps); 	for(int i = 0;isz;++i) 	{ 		if(ps->a[i] == x) 			return i; 	} 	return -1;//没找到 } 

3.9 顺序表在pos位置插入x

就是类似与头插,头插可以理解为在0位置前插入数据。

void InsertSeqlist(SL* ps,int pos,Datatype x) { 	assert(ps); 	SeqlistCapacity(ps); 	for(int i = ps->sz;i>=pos+1;--i) 	{ 		ps->a[i] = ps->a[i-1]; 	} 	ps->a[pos] = x;	 	ps->sz+=1; } 

3.10 顺序表删除pos位置的值

类似于头删

void EraseSeqlist(SL* ps,int pos) { 	assert(ps); 	assert(ps->sz!=0); 	for(int i = pos;isz-1;++i) 	{ 		ps->a[i] = ps->a[i+1]; 	} 	ps->sz -= 1; } 

4.代码整合

//seqlist.h #include  #include  #include   typedef int Datatype;//为了适用不同类型的顺序表 typedef struct SeqList { 	Datatype* a; 	int sz;//有效数据个数 	int capacity;//存储空间大小 }SL;   void InitSeqlist(SL* ps);  void DestorySeqlist(SL* ps);  void SeqlistCapacity(SL* ps);  void PopBack(SL* ps);  void PrintSeqlist(SL* ps);  void PushFront(SL* ps, Datatype x);  void PopFront(SL* ps);  int FindSeqlist(SL* ps, Datatype x);  void InsertSeqlist(SL* ps, int pos, Datatype x);  void EraseSeqlist(SL* ps, int pos);  void PushBack(SL* ps, Datatype x); //seqlist.c #include "seqlist.h"  void InitSeqlist(SL* ps) { 	ps->a = (Datatype*)malloc(sizeof(Datatype) * 3); 	if (ps->a == NULL)//扩容失败,直接退出程序 	{ 		perror("InitSeqlist"); 		exit(-1); 	} 	ps->sz = 0; 	ps->capacity = 3; }  void DestorySeqlist(SL* ps) { 	free(ps->a); 	ps->a = NULL; 	ps->sz = 0; 	ps->capacity = 0; }  void PushBack(SL* ps, Datatype x) { 	assert(ps); 	//检查空间是否已满 	SeqlistCapacity(ps); 	ps->a[ps->sz] = x; 	ps->sz += 1; }  void SeqlistCapacity(SL* ps) { 	if (ps->capacity == ps->sz)//满了 	{ 		Datatype* tmp = (Datatype*)realloc(ps->a, sizeof(Datatype) * 2*ps->capacity); 		if (tmp == NULL)//开辟失败 		{ 			perror("realloc"); 			exit(-1); 		} 		ps->a = tmp; 		ps->capacity *= 2; 	} }  void PopBack(SL* ps) { 	assert(ps); 	if (ps->sz > 0) 	{ 		ps->sz -= 1; 	} }   void PrintSeqlist(SL* ps) { 	for (int i = 0; i < ps->sz; ++i) 	{ 		printf("%d ", ps->a[i]); 	} 	printf("\n"); }  void PushFront(SL* ps, Datatype x) { 	assert(ps); 	SeqlistCapacity(ps); 	for (int i = ps->sz; i >= 1; --i) 	{ 		ps->a[i] = ps->a[i - 1]; 	} 	ps->a[0] = x; 	ps->sz += 1; }  void PopFront(SL* ps) { 	assert(ps); 	assert(ps->sz != 0); 	for (int i = 0; i < ps->sz - 1; ++i) 	{ 		ps->a[i] = ps->a[i + 1]; 	} 	ps->sz -= 1; }  int FindSeqlist(SL* ps, Datatype x) { 	assert(ps); 	for (int i = 0; i < ps->sz; ++i) 	{ 		if (ps->a[i] == x) 			return i; 	} 	return -1;//没找到 }  void InsertSeqlist(SL* ps, int pos, Datatype x) { 	assert(ps); 	SeqlistCapacity(ps); 	for (int i = ps->sz; i >= pos + 1; --i) 	{ 		ps->a[i] = ps->a[i - 1]; 	} 	ps->a[pos] = x; 	ps->sz += 1; }  void EraseSeqlist(SL* ps, int pos) { 	assert(ps); 	assert(ps->sz != 0); 	for (int i = pos; i < ps->sz - 1; ++i) 	{ 		ps->a[i] = ps->a[i + 1]; 	} 	ps->sz -= 1; }  //test.c #include "seqlist.h"  int main() { 	//测试 	/*SL sl; 	InitSeqlist(&sl); 	PushBack(&sl, 1); 	PushBack(&sl, 2); 	PushBack(&sl, 3); 	PushBack(&sl, 4); 	PushBack(&sl, 5); 	PushBack(&sl, 6); 	PrintSeqlist(&sl);  	PopBack(&sl); 	PopBack(&sl); 	PopBack(&sl); 	PopBack(&sl); 	PrintSeqlist(&sl); 	PopBack(&sl); 	PopBack(&sl); 	PopBack(&sl); 	PrintSeqlist(&sl);  	PushBack(&sl, 1); 	PushBack(&sl, 2); 	PushBack(&sl, 3); 	PushBack(&sl, 4); 	PushBack(&sl, 5); 	PushBack(&sl, 6); 	PushFront(&sl, 100); 	PushFront(&sl, 200); 	PrintSeqlist(&sl); 	InsertSeqlist(&sl, 0, 1000); 	PrintSeqlist(&sl);  	int pos = FindSeqlist(&sl, 100); 	PopFront(&sl); 	PopFront(&sl); 	PopFront(&sl);  	PopFront(&sl); 	PrintSeqlist(&sl);*/  	//printf("%d", pos); 	return 0; } 

相关内容

热门资讯

秒懂教程“微信链接牛牛群房卡怎... 随意玩是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:44346008许多玩家在游戏中会购买房卡来享...
房卡必备教程“金花大厅房卡链接... 微信网页牛牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:86909166许多玩家在游戏中会购买房...
金花大厅链接房卡怎么弄的/微信... 牛牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:44346008许多玩家在游戏中会购买房卡来享受...
一分钟推荐“微信金花房卡怎样购... 新神盾是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:86909166许多玩家在游戏中会购买房卡来享...
房卡必备教程“微信金花链接在哪... 微信炸金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房...
微信链接炸金花房卡开科技/微信... 微信炸金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:44346008许多玩家在游戏中会购买房卡...
安卓系统游戏昵称推荐,昵称背后... 亲爱的玩家们,你是不是在为你的安卓系统游戏昵称发愁呢?别急,今天我就来给你支支招,让你在游戏中脱颖而...
金花链接房卡怎么创建房间/创建... 金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房卡来享...
微信牛牛链接怎么制作/微信金花... 牛牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:44346008许多玩家在游戏中会购买房卡来享受...
正版授权“微信拼三张房卡怎么获... 新祥心牛牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:86909166许多玩家在游戏中会购买房卡...
安卓系统与苹果的区别,系统差异... 你有没有想过,为什么有些人偏爱安卓手机,而有些人却对苹果爱不释手呢?这其中的奥秘,可不仅仅是因为外观...
微信炸金花房卡在哪里充/微信链... 微信炸金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房...
去哪儿买微信金花房卡/创建金花... 金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房卡来享...
金花客服代理房卡获取方式/微信... 金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房卡来享...
炸金花微信建群自己开房卡/牛牛... 牛牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:86909166许多玩家在游戏中会购买房卡来享受...
ia实测“微信炸金花房卡怎么开... 微信炸金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房...
购买斗牛房卡联系方式/微信链接... 斗牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:86909166许多玩家在游戏中会购买房卡来享受...
房卡必备教程“牛牛房卡购买渠道... 新乐游是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房卡来...
斗牛房卡怎么购买/微信牛牛房卡... 斗牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:44346008许多玩家在游戏中会购买房卡来享受...
微信上玩炸金花充值方式/牛牛金... 牛牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:86909166许多玩家在游戏中会购买房卡来享受...