【C语言】从零开始:用C语言实现顺序表

欢迎来CILMY23的博客

本篇主题为 从零开始:用C语言实现顺序表

个人主页:CILMY23-CSDN博客

C语言专栏: http://t.csdnimg.cn/hQ5a9

Python系列专栏:http://t.csdnimg.cn/HqYo8

上一篇C语言博客: http://t.csdnimg.cn/I4Zgf

感谢观看,支持的可以给个一键三连,点赞关注+收藏。


目录

一、 什么是顺序表?

1.1 顺序表概念

1.2 顺序表结构及初始化

二、顺序表的功能实现

2.1 增 

2.1.1 头插

2.1.2 尾插

2.1.3 任意位置插入 

2.2 删

2.2.1 头删

2.2.2 尾删

2.2.3 任意位置删除 

2.3 查

2.4 改 

三、 顺序表其余功能

3.1 打印顺序表

3.2 销毁顺序表


本文前言

在学习完C语言后,我们扩展学习几种的数据结构,目的是为了最后的通讯录项目做铺垫

一、 什么是顺序表?

 如果不知道数据结构的概念可以看数据结构概念篇(http://t.csdnimg.cn/yPSMc

1.1 顺序表概念

在讲顺序表之前得先讲讲线性表

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

顺序表(Seqlist)是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存 储。在数组上完成数据的增删查改。

顺序表又分为静态和动态,而静态的顺序表就是固定的空间,那本篇主要以动态顺序表的实现为主。 

1.2 顺序表结构及初始化

 顺序表的结构如下所示:

typedef int SLDataType;

typedef struct SeqList
{
	SLDataType* a;			 // 起始位置
	size_t data;			 // 有效数据个数
	size_t capacity;		 // 空间容量
}SQ;

那在使用之前我们肯定是要初始化的,这里我们直接给了一个capacity = 4,意思是这个顺序表一开始就有4个空间(但这个时候实际还未创建好)

//顺序表的初始化
void SLInit(SL* sl)
{
	assert(sl);

	sl->a = NULL;
	sl->data = 0;
	sl->capacity = 4;
}

二、顺序表的功能实现

顺序表功能主要围绕四个部分,“增删查改”这四个字,当然我们还可以增加其他功能,这些是最基本的实现。 

 

2.1 增 

在插入前我们做的第一件事就是要看空间

空间的几种情况如下: 

因为该过程较为常用,我们使用函数进行封装,这样在每次插入前都检查一遍空间。因为一次只插入一个数据,所以当有效数据和空间相等的时候,说明此时已经没有足够空间了,那要进行扩容,如果我们没在初始化给顺序表一个空间,就要使用newcapacity 对 capacity 进行判断,多一步去检查capacity。

//顺序表的空间检查
void SLCheckCapacity(SL*sl)
{	
	//如果空间不够,就要扩容
	if (sl->data == sl->capacity)
	{
		SLDataType* psl;
		psl = (SLDataType*)realloc(sl->a, sl->capacity * 2 * sizeof(SLDataType));
		if (psl == NULL)
		{
			perror("realloc fail");
			return 1;
		}
		sl->a = psl;
		sl->capacity = sl->capacity*2;
	}
}

2.1.1 头插

//顺序表的头插
void SLPushFront(SL* sl, SLDataType x)
{
	assert(sl);
	//检查空间
	SLCheckCapacity(sl);
	//插入数据,前要移动数据
	for (size_t i = sl->data; i > 0; i--)
	{
		//从末尾开始移动数据
		sl->a[i] = sl->a[i - 1];
	}
	//移动完数据开始插入数据
	sl->a[0] = x;
	sl->data++;
}

2.1.2 尾插

//顺序表的尾插
void SLPushBack(SL* sl, SLDataType x)
{
	assert(sl);
	//插入前,检查空间
	SLCheckCapacity(sl);
	//插入数据
	sl->a[sl->data] = x;
	sl->data++;
}

2.1.3 任意位置插入

我们这里说的是在任意位置之前插入数据

//任意位置插入
void SLInsert(SL* sl, int pos, SLDataType x)
{
	assert(sl);
	assert(pos >= 0 && pos <= sl->data);
	//检查空间
	SLCheckCapacity(sl);
	//数据移动
	for (int i = sl->data - 1; i >= pos; i--)
	{
		sl->a[i + 1] = sl->a[i];
	}

	sl->a[pos] = x;
	sl->data++;
}

2.2 删

在删除的时候要判断顺序表是否为空,所以我们使用一个布尔类型来判断顺序表是否为空

//判断顺序表是否为空
bool SLIsEmpty(SL* sl)
{
	assert(sl);
	//当有效数据为0就为空的顺序表
	return sl->data == 0;
}

2.2.1 头删

 在删除的时候一定要保证size大于0,当然我还是更喜欢在删除的时候选择这种柔和的方式,当然你也可以选择用assert方式。

void SLPopFront(SL* sl)
{
	assert(sl);
	if (sl->data > 0)
	{
		for (int i = 0; i < sl->data; i++)
		{
			sl->a[i] = sl->a[i - 1];
		}
		sl->data--;
	}
}

2.2.2 尾删

 注意,我们删除的时候不能让有效数据小于0.

//顺序表的尾删
void SLPopBack(SL* sl)
{
	assert(sl);
	//保证有效数据大于0
	if(sl->data > 0)
	sl->data -= 1;
}

2.2.3 任意位置删除 

注意pos不能等于 sl->data ,因为这个位置没有数据啦 

//任意位置删除
void SLErase(SL* sl, int pos)
{
	assert(sl);
	assert(!SLIsEmpty(sl));

	//对pos进行检查
	assert(pos >= 0 && pos < sl->data);

	//数据移动
	for (int i = pos; i < sl->data - 1; i++)
	{
		sl->a[i] = sl->a[i + 1];
	}

	sl->data--;
}

2.3 查

在顺序表中查询数据,如果找到了则返回下标位置,如果找不到就返回-1

//顺序表查找数据
int SLFind(SL* sl, SLDataType x)
{
	assert(sl);
	assert(!SLIsEmpty(sl));
	int i = 0;
	for (i = 0; i < sl->data; i++)
	{
		if (sl->a[i] == x)
		{
			return i;
		}
	}
	if (i == sl->data)
		return -1;
}

2.4 改 

在顺序表中修改指定位置的数据

//顺序表修改数据
void SLChange(SL* sl, SLDataType x)
{
	assert(sl);
	assert(!SLIsEmpty(sl));
	int i = 0;
	for (i = 0; i < sl->data; i++)
	{
		if (sl->a[i] == x)
		{
			sl ->a a[i] = x;
		}
	}
}

三、 顺序表其余功能

3.1 打印顺序表

//顺序表的打印
void SLPrint(SL* sl)
{
	if (sl->data != 0)
	{
		int i = 0;
		for (i = 0; i < sl->data;i++)
		{
			printf("%d ", sl->a[i]);
		}
		printf("\n");
	}
}

3.2 销毁顺序表 

有顺序表的初始化,那就有顺序表的销毁,因为是动态内存,所以我们就要用到free函数来释放空间

//顺序表的销毁
void SLDestroy(SL* sl)
{
	if (sl->a != NULL)
	{
		free(sl->a);
		sl->a = NULL;
		sl->capacity = 0;
		sl->data = 0;
	}
}

 感谢各位同伴的支持,本期顺序表就讲解到这啦,更详细的可以看,【数据结构和算法】4.超详细解析动态顺序表的实现(图文解析,附带源码)-CSDN博客

如果你觉得写的不错的话,可以给个一键三连,点赞,关注+收藏,若有不足,欢迎各位在评论区讨论。      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值