前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【通讯录项目 (2 / 3)】基于顺序表的通讯录实现——顺序表功能实现

【通讯录项目 (2 / 3)】基于顺序表的通讯录实现——顺序表功能实现

作者头像
叫我龙翔
发布2024-01-30 13:56:55
1260
发布2024-01-30 13:56:55
举报
文章被收录于专栏:就业 C++ 综合学习

基于顺序表的通讯录实现——顺序表功能实现

顺序表功能实现
  • 基于顺序表的通讯录实现——顺序表功能实现
    • 1 初始化与销毁
      • 1.1 初始化
      • 1.2 销毁
    • 2 头部插入与删除
      • 2.1 头部插入
        • 2.1.1检查容量
        • 2.1.2 插入数据
      • 2.2 头部删除
        • 2.2.1 检测数据是否为空
    • 3 尾部插入与删除
      • 3.1 尾部插入
      • 3.2 尾部删除
    • 4 指定位置插入与删除
      • 4.1 指定位置插入
        • 4.1.1 查找数据
      • 4.2 指定位置删除
    • 5 打印顺序表
      • 5.1 打印顺序表
    • 6 结束语
  • 期待下一次与你见面!!!

经过上一篇文章我们对顺序表有了一个初步的认识,下面我们将通过C语言实现顺序表的功能,包括: 增加数据 删除数据 查找数据 修改数据 可以把顺序表看作一种特殊的数组,我们下面将要进行的操作是基于 数组 数组操作 动态内存管理等基本功能实现的

顺序表功能
顺序表功能

1 初始化与销毁

顺序表底层
顺序表底层

这里我们用“ SLDataType”来代替传统的int char等关键字,这样以后,就可以避免在修改变量类型的时候,进入"地狱模式"。

1.1 初始化
代码语言:javascript
复制
void SLInit(SL* ps)
{
	assert(ps);//断言检测是否为空指针
	ps->a = NULL;//初始化
	ps->size = ps->capacity = 0;//初始化
}

注意这里我们使用的是“传址操作”,这样可以在原有基础上修改数据信息。

1.2 销毁
代码语言:javascript
复制
void SLDestroy(SL* ps)
{
	assert(ps);//断言检测是否为空指针
	free(ps->a);//释放顺序表数据空间
	ps->size = ps->capacity = 0;//销毁归零
	ps->a = NULL;//避免“野指针”
}

注意这里我们使用的是“传址操作”,这样可以在原有基础上修改数据信息。

初始化和销毁的操作比较简单,不在做详细阐释。观察代码即可。

2 头部插入与删除

2.1 头部插入
代码语言:javascript
复制
void SLPushFront(SL* ps, SLDataType x)
 {
	assert(ps);//断言检测是否为空指针
	//判断空间是否足够,不够则扩容
	SLCheckCapacity(ps);
	//空间足够,历史数据后移一位
	for (size_t i = ps->size; i > 0; i--){
		ps->a[i] = ps->a[i - 1];
	}
	ps->a[0] = x;
	ps->size++;
}

这里我们插入的时候需要考虑空间是否足够 于是我们单独分装一个函数进行容量判断

2.1.1检查容量
代码语言:javascript
复制
void SLCheckCapacity(SL* ps)
{

	if (ps->size == ps->capacity){
		//三目操作符,为零设为 4,反之为原来空间的2倍
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		//开辟空间
		SLDataType* tmp = (SLDataType*)realloc(ps->a,newcapacity*sizeof(SLDataType));
		//检查开辟是否成功
		if (tmp == NULL){
			perror("realloc fail!");
			return;
		}
		ps->a = tmp;//转移新空间
		ps->capacity = newcapacity;//设置新容量                                           
	}
}

我们一行一行的解读 1 首先判断原顺序表是否为空,如果为空则设置为四个容量,反之为原来二倍 倍数原则上可以设置为任意大小,这里之所以设置为二倍,是因为这样利用率最高 2 然后开辟空间 我们重温一下realloc函数

在这里插入图片描述
在这里插入图片描述

注意“size”代表新的空间大小,而不是需要增加的空间大小 开辟完空间即可进行对顺序表的扩容

2.1.2 插入数据
在这里插入图片描述
在这里插入图片描述

头部插入只需在检查容量之后,依次移动顺序表数据即可,再将数据插入到头部即可,类似数组操作。 插入完成之后不要忘记将 size 加 1

2.2 头部删除
代码语言:javascript
复制
void SLPopFront(SL* ps)
{
	assert(ps);//断言检测是否为空指针
	assert(!SLIsEmpty(ps));//断言检测指针指向是否为空数据。
	for (int i = 0; i < ps->size - 1 ; i++)
	{
		ps->a[i] = ps->a[i + 1]; // a[size-2]=a[size-1] (模拟最后一次操作)
	}
	ps->size--;
}

头部删除非常简单,将顺序表中的数据从第二个依次向前覆盖即可。

2.2.1 检测数据是否为空
代码语言:javascript
复制
bool SLIsEmpty(SL* ps) {
	assert(ps);
	//这样子是不对的,这里只能判断空间是否足够
	//return ps->size == ps->capacity;
	return ps->size == 0;
}

使用断言即可,切记不要用“ps->size == ps->capacity”这样只能判断空间是否足够

3 尾部插入与删除

尾部操作相对于头部更加简单

3.1 尾部插入
代码语言:javascript
复制
void SLPushBack(SL* ps, SLDataType x)
{
	assert(ps);//断言检测是否为空指针
	SLCheckCapacity(ps);//判断空间是否足够,不够则扩容
	ps->a[ps->size++] = x;
}

检查空间之后,进行赋值即可。

3.2 尾部删除
代码语言:javascript
复制
void SLPopBack(SL* ps)
{
	assert(ps);//断言检测是否为空指针
	assert(!SLIsEmpty(ps));//断言检测指向是否为空数据。
	ps->size--;
}

在断言并检测数据之后,将size减1即可,这里不需要将删除的数据进行处理,避免出现数据类型的不符合。

4 指定位置插入与删除

指定位置的插入与删除需要一步“查找”目标数据操作,才可以进行精准操作。 当然也可以不进行“操作”,直接对位置进行修改。

4.1 指定位置插入
代码语言:javascript
复制
void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);//断言检测是否为空指针
	SLCheckCapacity(ps);//判断空间是否足够,不够则扩容
	if (pos >= 0 && pos < ps->size)//防止越界操作
	{
		for (int i = ps->size; i > pos; i--)
		{
			ps->a[i] = ps->a[i - 1];//a[pos+1]=a[pos]
		}
		ps->a[pos] = x;
		ps->size++;
	}
	else
		assert(pos);//越界进行停止
}

pos是要修改的位置,再检测容量和检测pos是在合理范围内之后,即可进行移动插入操作。 如果要精准插入到一个数据之前则需要对pos进行操作。

4.1.1 查找数据
代码语言:javascript
复制
    pos = SLFind(SL, 5)//举例 “5”
//函数内部
int SLFind(SL* ps, SLDataType x)
{
	assert(ps);//断言检测是否为空指针
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->a[i] == x)
			return i;//找到返回偏移量 i 
		else
			continue;
	}
	return -1;//没找到
}

这样便可以进行准确插入。

4.2 指定位置删除
代码语言:javascript
复制
void SLErase(SL*ps,int pos)
{                                                                                          
	assert(ps);//断言检测是否为空指针
	if (pos >= 0 && pos < ps->size)
	{
		for (int i = pos; i < ps->size - 1; i++)
		{
			ps->a[i] = ps->a[i + 1];  //a[size-2]=a[size-1](模拟最后一次操作)
		}
		ps->size--;
	}
	else
		assert(pos);
}

删除较为简单,对pos位置进行覆盖操作即可。注意size减1。

5 打印顺序表

打印操作十分简单,与打印数组类似。

5.1 打印顺序表
代码语言:javascript
复制
void SLPrint(SL* ps)
{
	assert(ps);//断言检测是否为空指针
	int i = 0;
	//依次打印数据即可
	for (i = 0; i < ps->size; i++)
	{
		printf("%2d", ps->a[i]);
	}
	printf("\n");
}

由于我们这里展示的是最简单的顺序表。所以打印十分简单。

6 结束语

顺序表的功能我们已经实现,我们使用的是最简单的顺序表,所以整个过程看起来没有困难。在下一篇文章中我们将进行通讯录的实现。 在通讯录里,顺序表的类型不在是简单的" int ",而是结构体类型。 下面给出通讯录的基本功能供大家参考预习。

在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-01-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基于顺序表的通讯录实现——顺序表功能实现
    • 顺序表功能实现
      • 1 初始化与销毁
        • 1.1 初始化
        • 1.2 销毁
      • 2 头部插入与删除
        • 2.1 头部插入
        • 2.2 头部删除
      • 3 尾部插入与删除
        • 3.1 尾部插入
        • 3.2 尾部删除
      • 4 指定位置插入与删除
        • 4.1 指定位置插入
        • 4.2 指定位置删除
      • 5 打印顺序表
        • 5.1 打印顺序表
      • 6 结束语
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档