数据结构与算法:01——顺序表(C++描述)
提示:本文章适合学习完指针与类与对象的C++学习者
文章目录
前言
提示:顺序表解决的问题是什么?
顺序表能够实现储存和访问元素、动态扩展、插入和删除、排序和查找等操作。
一、顺序表介绍
顺序表是一种常见的数据结构,它是一种线性表,其中的元素按照一定的顺序排列。顺序表的实现是通过数组或类似的连续存储空间来存储元素。适用于需要快速访问和修改元素的场景,但不适用于频繁插入和删除元素的场景。
二、顺序表代码操作
1.顺序表结构
顺序表的结构图如下所示(示例):
可以看出顺序表的存储地址是连续的,并且通过指针可以实现数据的插入删除、自动扩容等操作,并且顺表由三部分组成:size容量、count元素个数、*data数据。
我们要实现顺序表的以下功能:
#include <iostream>
#include<ctime>
using namespace std;
class vector
{
public:
// 初始化顺序表
vector(int n)`;
//判断顺序表是否为空
bool is_Empty();
//判断顺序表是否已满
bool is_Full();
//返回顺序表长度
int Size();
// 插入数据
// 参数pos表示在pos位置插入val数值
bool insert(int pos, int val) ;
// 删除元素
bool erase(int pos);
// 遍历顺序表并显示元素
void display();
// 销毁顺序表
void clear();
private:
//容量
int size;
//元素个数
int count;
//数据
int* data;
//顺序表扩容
bool expand()
};
2.构造函数
示例代码如下所示:
// 初始化顺序表
vector(int n)
{
// 顺序表的长度为n
this->size = n;
// 顺序表的元素个数为0
this->count = 0;
// 新建一个数据
this->data = new int[size];
}
这里的new int[size]类似于创建一个新的指针数组用于开辟一个size大小的内存空间,这样做的好处是,方便控制数组的内存大小,后面扩容操作会使用。
3.判断顺序表是否为空/是否已满/返回顺序表长度
判断顺序表是否为空的关键是搞清容量与元素个数的关系:
1、当元素个数为零时,顺序表为空。
2、当元素个数等于容量时,顺序表已满
下面是示例代码:
//判断顺序表是否为空
bool is_Empty()
{
if(this->count == 0)
{
return true;
}
else
{
return false;
}
}
//判断顺序表是否已满
bool is_Full()
{
if(this->count == this->size)
{
return true;
}
else
{
return false;
}
}
//返回顺序表长度
int Size()
{
return this->count;
}
4.插入
插入操作的完成需要满足一下条件:
1、顺序表未满,或扩容成功。
2、插入位置在合理的范围内。
在此之前,我们先看看如何进行扩容:
扩容操作可以写在public下、也可以写在private下,取决于个人需求。
扩容操作的步骤是:
1、创建一个有2 * size大小的新容器newData
2、将原来data内的数据存入newData
3、将data原来的数据释放
4、令data等于newData 5、修改容量size,使其等于2 * size
下面是示例代码:
//顺序表扩容
bool expand() {
//显示提示信息,将原本的顺序表长度扩容到两倍
cout << "expand vector from " << size << " to " << size * 2 << endl;
//创建一个新的两倍长的数据容器
int* newData = new int[size * 2];
//判断newData是否创建成功
if (newData == nullptr) {
return false;
}
//将原本data内的数据写进newData里面
for (int i = 0; i < count; i++) {
newData[i] = data[i];
}
//释放原来data内的数据
delete[] data;
//将newData与data相等
data = newData;
//将size扩大到两倍
size = size * 2;
return true;
}
下面是插入的示例代码:
// 插入数据
// 参数pos表示在pos位置插入val数值
bool insert(int pos, int val) {
//判断顺序表是否已满
if (is_Full()) {
if (!expand()) {
//这个代码段检查向量是否已满,如果是,则调用expand()函数进行扩容。
//否则,跳过扩容的步骤并直接执行插入元素的操作。因此,即使没有显式调用expand()函数,
//向量也会自动扩容。
return false;
}
}
else if (pos < 0 || pos > count) {
return false;
}
for (int i = count; i > pos; i--) {
data[i] = data[i - 1];
}
data[pos] = val;
count++;
return true;
}
下面的循环的原理是下表为 i 的元素被下标为 i - 1的元素取代。
for (int i = count; i > pos; i--) {
data[i] = data[i - 1];
}
运行下面的代码,感受插入数据操作:
#include<iostream>
using namespace std;
int main()
{
int a[10] = { 1,3,4,5,6 };
for (int i = 5; i > 1; i--)
{
a[i] = a[i-1];
}
a[1] = 2;
for (int i = 0; i < 6; i++)
{
cout << a[i] << " ";
}
return 0;
}
5、删除
删除操作需要满足的条件是:
1、顺序表不为空
2、删除的元素位置正确
下面是示例代码:
// 删除元素
bool erase(int pos)
{
if (pos < 0 || pos >= this->count)
{
return false;
}
else if(this->is_Empty())
{
return false;
}
else
{
for (int i = pos + 1; i < this->count; i++)
{
this->data[i - 1] = this->data[i];
}
this->count--;
return true;
}
}
6、遍历
示例代码如下所示:
// 遍历顺序表并显示元素
void display()
{
if (this->count == 0)
{
return;
}
else
{
for (int i = 0; i < this->count; i++)
{
cout << this->data[i] << " ";
}
cout << endl;
}
}
7、销毁顺序表
// 销毁顺序表
void clear()
{
delete[] this->data;
this->data = nullptr;
this->size = 0;
this->count = 0;
}
三、完整代码
#include <iostream>
#include<ctime>
using namespace std;
class vector
{
public:
// 初始化顺序表
vector(int n)
{
// 顺序表的长度为n
this->size = n;
// 顺序表的元素个数为0
this->count = 0;
// 新建一个数据
this->data = new int[size];
}
//判断顺序表是否为空
bool is_Empty()
{
if(this->count == 0)
{
return true;
}
else
{
return false;
}
}
//判断顺序表是否已满
bool is_Full()
{
if(this->count == this->size)
{
return true;
}
else
{
return false;
}
}
//返回顺序表长度
int Size()
{
return this->count;
}
// 插入数据
// 参数pos表示在pos位置插入val数值
bool insert(int pos, int val) {
//判断顺序表是否已满
if (is_Full()) {
if (!expand()) {
//这个代码段检查向量是否已满,如果是,则调用expand()函数进行扩容。
//否则,跳过扩容的步骤并直接执行插入元素的操作。因此,即使没有显式调用expand()函数,
//向量也会自动扩容。
return false;
}
}
else if (pos < 0 || pos > count) {
return false;
}
for (int i = count; i > pos; i--) {
data[i] = data[i - 1];
}
data[pos] = val;
count++;
return true;
}
// 删除元素
bool erase(int pos)
{
if (pos < 0 || pos >= this->count)
{
return false;
}
else if(this->is_Empty())
{
return false;
}
else
{
for (int i = pos + 1; i < this->count; i++)
{
this->data[i - 1] = this->data[i];
}
this->count--;
return true;
}
}
// 遍历顺序表并显示元素
void display()
{
if (this->count == 0)
{
return;
}
else
{
for (int i = 0; i < this->count; i++)
{
cout << this->data[i] << " ";
}
cout << endl;
}
}
// 销毁顺序表
void clear()
{
delete[] this->data;
this->data = nullptr;
this->size = 0;
this->count = 0;
}
private:
int size;
int count;
int* data;
//顺序表扩容
bool expand() {
//显示提示信息,将原本的顺序表长度扩容到两倍
cout << "expand vector from " << size << " to " << size * 2 << endl;
//创建一个新的两倍长的数据容器
int* newData = new int[size * 2];
//判断newData是否创建成功
if (newData == nullptr) {
return false;
}
//将原本data内的数据写进newData里面
for (int i = 0; i < count; i++) {
newData[i] = data[i];
}
//释放原来data内的数据
delete[] data;
//将newData与data相等
data = newData;
//将size扩大到两倍
size = size * 2;
return true;
}
};
int main()
{
srand(time(0));
vector v(2);
v.insert(0,1);
v.insert(0,2);
v.insert(0,3);
v.insert(0,4);
v.insert(0,5);
v.insert(0,6);
v.insert(0,7);
v.insert(0,8);
v.display();
return 0;
}
总结
顺序表是一个高级的数组,能够实现很多数组实现不了的功能。
这是本系列的第一篇文章,希望获得你们的大拇指与五角星,点赞越多更新越快。(doge)