一篇文章带你总结基础数据结构————顺序表

1.什么是顺序表

顺序表是一种线性表的存储结构,它的元素按照顺序依次存放在一块连续的存储空间中。顺序表可以通过下标来访问和操作其中的元素,因此具有随机访问的特点。

顺序表的优点是存储结构简单,访问元素的时间复杂度为O(1),即常数时间。同时,顺序表的插入和删除操作也比较简单,时间复杂度为O(n),其中n为表中元素的个数。

尽管stl中有相应的函数,但作为数据结构的初学者,顺序表还是很有意义学习的。

2.顺序表包含哪些部分

作为一个集成结构,它具有,初始化,销毁,扩容,头插,尾插,头删,尾删,任意删除和插入功能。如头文件所示:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

typedef int SLDataType;

typedef struct seqlist {
	SLDataType* a;//数组
	int size;//记录
	int capacity;//最大容量
}SL;

void SLInit(SL* psl);//初始化
void SLDestroy(SL* psl);//销毁

void SLPrint(SL* psl);//打印
void SLCheckCapacity(SL* psl);//检查最大访问

void SLPushBack(SL* psl, SLDataType x);//尾插
void SLPushFront(SL* psl, SLDataType x);//头插
void SLPopBack(SL* psl);//尾删
void SLPopFront(SL* psl);//前删

// 任意下标位置的插入删除
void SLInsert(SL* psl, int pos, SLDataType x);
void SLErase(SL* psl, int pos);

首先需要创建一个结构体SeqList,包含数组,当前数据大小,和最大容量三个参数。通过实时变化动态控制顺序表大小。

3.实现各部分函数功能。

1.初始化

void SLInit(SL* psl)
{
	assert(psl);
	psl->a = NULL;
	psl->size = 0;
	psl->capacity = 0;
}

该函数有一个参数,即为所创建的结构体类型指针,记得一定是指针,否则无法进行函数局部内修改。分别将三个量赋为零。初始化完成。

2.创建一个扩容函数。

void SLCheckCapacity(SL* psl)
{
	assert(psl);

	if (psl->capacity == psl->size)
	{
		int newcapacity = psl->capacity == 0 ? 4 : psl->capacity * 2;
		SLDataType* tem = (SLDataType*)realloc(psl->a, sizeof(SLDataType) * newcapacity);

		if (tem == NULL)
		{
			return ;
		}
		psl->a = tem;
		psl->capacity = newcapacity;
	}
}

老规矩,assert断言一下。

这里我们思路是看当前空间是否等于最大容量,如果相等则表示内存上限,需要扩容。

接下来一个小细节,使用一个三目运算符,将初始开辟和再次开辟巧妙结合,之后设置一个临时变量开辟空间,防止开辟失败污染原始数据。

进行判断后我们将开辟空间和最新容量返回顺序表。

3.创建头插和尾插函数

void SLPushBack(SL* psl, SLDataType x)
{
	assert(psl);
	SLCheckCapacity(psl);
	psl->a[psl->size] = x;
	psl->size++;
}
void SLPushFront(SL* psl, SLDataType x)
{
	assert(psl);
	SLCheckCapacity(psl);
	int end = psl->size - 1;
	while (end >= 0)
	{
		psl->a[end + 1] = psl->a[end];
		--end;
	}
	psl->a[0] = x;
	psl->size++;
}

函数参数都为结构体指针和待插入数x.

老规矩assert断言

由于是插入,所以判断是否扩容,防止数组越界。

尾插比较简单,仅需将数据放在size的位置,值得注意的是,size我们每次后置++,所以size的位置就是,原数据下一个位置。

头插的思路则需要将整个数组向后移动一位,再将x放入a[0]。

记得size++,因为是插入。

4.任意位置插入。

void SLInsert(SL* psl, int pos, SLDataType x)
{
	assert(psl);
	assert(pos>=0&&pos <= psl->size);
	SLCheckCapacity(psl);
	int end = psl->size - 1;
	for (int i = end; i >= pos; i--)
	{
		psl->a[i + 1] = psl->a[i];
	}
	psl->a[pos] = x;
	psl->size++;

}

三个参数,比以往多了一个Pos代表要插入位置。

老规矩,assert断言,并且判断所给位置是否合理。

任意插入类似于头插,将pos之后统一后运动即可。控制好下标就好。

5.删除系统,头删,尾删,随意删。

void SLPopBack(SL* psl)
{
	assert(psl);
	psl->size--;
}
void SLPopFront(SL* psl)
{
	assert(psl);
	int end = psl->size - 1;
	for (int i = 1; i <= end; i++)
	{
		psl->a[i - 1] = psl->a[i];
	}
	psl->size--;
}
void SLErase(SL* psl, int pos)
{
	assert(psl);
	for (int i = pos; i < psl->size - 1; i++)
	{
		psl->a[i] = psl->a[i + 1];
	}
	psl->size--;
}

尾删依旧最简单,使用“以覆盖代替删除”,直接将size--即可,不访问即为删除。

值得注意的是这几个删除函数不用扩容函数,仅需assert一下。

要删除的位置直接用下一个位置数据覆盖就好,每个函数后需要size--.因为是删除函数。

6.销毁空间

void SLDestroy(SL* psl)
{
	assert(psl);
	if (psl->a != NULL)
	{
		free(psl->a);
		psl->a = NULL;
		psl->size = 0;
		psl->capacity=0;
	}

}

因为是动态内存管理,所以一定要释放内存,防止内存泄漏。先free,再将指针置空。各数据归零。

4.运行调试。

写一个test文件来运行各个功能。

#include<stdio.h>
#include"seqlist.h"
void TestSL1()
{
	SL sl;
	SLInit(&sl);
	//尾插
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPrint(&sl);
	//头插
	SLPushFront(&sl, 5);
	SLPushFront(&sl, 6);
	SLPushFront(&sl, 7);
	SLPushFront(&sl, 8);
	SLPrint(&sl);
	//尾删
	SLPopBack(&sl);
	SLPrint(&sl);
	//头删
	SLPopFront(&sl);
	SLPrint(&sl);
	//任意插入
	SLInsert(&sl, 4, 18);
	SLPrint(&sl);
	//任意删除
	SLErase(&sl, 3);
	SLPrint(&sl);


	SLPrint(&sl);
	SLDestroy(&sl);
}
int main()
{
	TestSL1();
	return 0;
}

接下来就坐等f5:

 YES!!!成功,各个功能正常,快去亲手尝试吧!!!

创作不易,感谢三联

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

强sir的世界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值