顺序表的总结及模拟实现

目录

一.线性表

二.顺序表

1.概念

2.结构

3.要实现的接口函数

三.模拟实现顺序表

1.定义出顺序表的基本结构

2.实现检查扩容功能

3.实现尾插

4.实现尾删

5.实现头插和头删

6.查找

7.修改

8.遍历

9.在指定位置插入和删除

四.顺序表的优缺点及思考

a.顺序表的弊端


一.线性表

在谈顺序表前,我们要先说说线性表了,线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

说白了,线性表在逻辑上就是一条线性结构,数据之间的排列是一个接一个的,尽管它们在物理上不一定是线性的;

如下图所示两种线性表的逻辑结构,它们的数据看起来都是首尾相连的;

二.顺序表

1.概念

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

2.结构

顺序表可以分为静态顺序表和动态顺序表,静态顺序表采用定长数组的形式来存储元素,而动态顺序表则可以根据需要进行扩容,相对而言还是动态顺序表更加实用,我们这里实现的也是动态顺序表。

静态与动态顺序表的结构示意如下(c语言版)

其中,SLDataType是表示指定类型的宏定义,在c++中可以用模版来代替!size为有效元素的个数,capacity为数组的容量,不够时可以通过realloc扩容;

3.要实现的接口函数

三.模拟实现顺序表

模拟实现我们采用c++的方式来,因为写起来更方便,而且初始化和销毁都包含在构造函数和析构函数中了,无需我们手动调用;

1.定义出顺序表的基本结构

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstdlib>
#include <assert.h>
using namespace std;
using DataType = int;
class seqList
{
public:
	
	seqList()
		:_num(nullptr),
		_size(0),
		_capacity(0)
	{}

	~seqList()
	{
		delete(_num);
		_size = 0;
		_capacity = 0;
	}

private:
	DataType* _num;
	int _size;
	int _capacity;
};

2.实现检查扩容功能

因为我们往数组里添加数据可能遇到数组空间不够的情况,所以要能检测到这种需要进行扩容的情况!

cpp 复制代码
void SeqListCheckCapacity()
{
	if (_size == _capacity)
	{
		int newcapacity = _capacity == 0 ? 4 : _capacity * 2;
		DataType* tmp = (DataType*)realloc(_num, sizeof(DataType) * newcapacity);
		if (tmp == nullptr)
		{
			perror("扩容出错:");
			return;
		}
		_num = tmp;
		_capacity = newcapacity;
	}
}

3.实现尾插

插入数据之前,要先检查一下当前是否需要扩容了,这样能够确保空间足够,插入数据之后不要忘记维护代表元素个数的_size;

cpp 复制代码
void SeqListPushBack(DataType x)
{
	SeqListCheckCapacity();
	_num[_size++] = x;
}

4.实现尾删

删除数据前要先确保数组内还有剩余数据,如果有,只需要将元素个数减一即可,因为我们查找和遍历顺序表时都是通过_size来进行的!

cpp 复制代码
void SeqListPopBack()
{
	assert(_size > 0);
	_size--;
}

5.实现头插和头删

只要是插入,就要首先判断扩容,只要是删除,就要先判断是否有数据;

头插和头删的共同点是都要移动元素,对于头插,我们在顺序表头部插入元素之前,必须将原来的所有数据整体往右移一位,才能给插入数据腾出空间,此时要头插注意移动的方法,必须是从右往左进行的,每次都选取要移动到的位置,然后将左边的数移到该位置;如果从左往右依次移动,会出现左边值覆盖右边值的情况!

尾删要先将数据向左集体移动一位,采用从左往右依次移动一位的方式;

cpp 复制代码
void SeqListPushFront(DataType x)
{
	SeqListCheckCapacity();
	for (int i = _size; i > 0; i--)
	{
		_num[i] = _num[i - 1];
	}
	_num[0] = x;
	_size++;
}
cpp 复制代码
void SeqListPopFront()
{
	assert(_size > 0);
	for (int i = 0; i < _size - 1; i++)
	{
		_num[i] = _num[i + 1];
	}
	_size--;
}

6.查找

没啥好说的,就是遍历数组找关键值

cpp 复制代码
int SeqListFind(DataType x)
{
	for (int i = 0; i < _size; i++)
	{
		if (_num[i] == x)
		{
			return i;
		}
	}
	return -1;

}

7.修改

cpp 复制代码
void SeqListModity(int pos,DataType x)
{
	assert(pos >= 0 && pos < _size);
	_num[pos] = x;
}

8.遍历

cpp 复制代码
	void SeqListPrint()
	{
		for (int i = 0; i < _size; i++)
		{
			printf("%d ", _num[i]);
		}
	}

9.在指定位置插入和删除

要注意的地方前面都已经强调过了,就是要注意插入前的检查扩容、元素的移动方式、size的维护、删除前的检查剩余数据

cpp 复制代码
void SeqListInsert(int pos, DataType x)
{
	assert(pos >= 0 && pos < _size);
	SeqListCheckCapacity();

	for (int i = _size; i > pos; i--)
	{
		_num[i] = _num[i - 1];
	}
	_num[pos] = x;
	_size++;
}
void SeqLIstDelete(int pos)
{
	assert(pos >= 0 && pos < _size);
	for (int i = pos; i < _size - 1; i++)
	{
		_num[i] = _num[i + 1];
	}
	_size--;
}

四.顺序表的优缺点及思考

a.顺序表的弊端

1. 中间/头部的插入删除,由于要整体移动元素,所以时间复杂度为O(N)
2. 由于realloc的特性:

  1. 原地调整:如果原内存块后有足够的空间,realloc会直接扩展内存块,而无需移动数据。
  2. 重新分配:如果原内存块后空间不足,realloc会分配一块新的内存,并将原数据复制到新内存中,同时释放原内存块。

所以增容可能需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到 200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。

b.顺序表的优点

1.随机访问效率高

顺序表最大的优点是支持随机访问,通过下标可以直接访问任意位置的元素,时间复杂度为O(1)。这使得顺序表在需要频繁查找或按索引访问元素的场景中表现出色,比如数组操作。

2.存储密度高

顺序表在内存中是连续存储的,不需要额外的空间来存储元素之间的逻辑关系,因此存储密度高。相比链表等结构,顺序表在存储相同数量元素时占用的内存更少。

3.缓存友好

由于顺序表在内存中是连续存储的,访问元素时具有良好的局部性,能够充分利用CPU缓存机制,提高访问速度。这一点在处理大量数据时尤为重要。

相关推荐
_多拉不懂A梦1 小时前
FFmepg源码系列-avformat_open_input()
c++·ffmpeg·音视频
源远流长jerry2 小时前
OpenHarmony概述与使用
c语言·c++·鸿蒙系统
艾莉丝努力练剑2 小时前
深入详解C语言的循环结构:while循环、do-while循环、for循环,结合实例,讲透C语言的循环结构
c语言·开发语言·c++·学习
Boop_wu2 小时前
[ 数据结构 ] 时间和空间复杂度
数据结构
紫洋葱hh3 小时前
【数据结构】二叉搜索树
数据结构
·白小白4 小时前
【数据结构】——栈(Stack)的原理与实现
c语言·开发语言·数据结构
类球状6 小时前
数据结构(一)顺序表
数据结构
郝学胜-神的一滴6 小时前
C++中的`auto`与`std::any`:功能、区别与选择建议
开发语言·c++·程序人生·算法
Rain_is_bad7 小时前
初识c语言————排序方法
c语言·开发语言·数据结构