【知识框架】
线性表(List):零个或多个数据元素的有限序列
顺序表是一种线性表的存储结构,它以一组连续的存储单元来存储数据元素,数据元素之间的逻辑关系通过元素在存储空间中的相对位置来表示。
顺序表的特点是元素存储位置相邻,可以通过下标来访问元素,时间复杂度为O(1)。由于元素的存储位置是连续的,所以在插入和删除元素时需要移动其他元素,时间复杂度为O(n)。
顺序表的优点是访问元素快速,插入和删除元素较慢。适用于频繁访问元素的场景。
顺序表的缺点是插入和删除操作较慢,需要移动其他元素。当插入和删除操作频繁时,会导致性能下降。
在实际应用中,顺序表的大小是固定的,如果元素的数量超过了顺序表的大小,需要重新分配更大的空间并将原来的元素复制过去,这样的操作是比较耗时的。为了解决这个问题,可以采用动态顺序表,即在需要扩容时动态分配更大的空间。
【代码解析】
1.创建顺序表结构
先写一个顺序表的结构框架,在里面定义一些需要用到的变量,如:元素elements,大小size,容量capacity
#include<iostream>
#define eleType int
using namespace std;
struct seqlist {
eleType* elements;
int size;
int capacity; //size<=capacity
};
2.初始化顺序表
在使用顺序表之前需要将其初始化,并申请空间存放数组
void initializeList(seqlist* list, int capacity) {
list->elements=new eleType [capacity]; //list获取元素,申请空间存放数组
list->size = 0; //初始化空间为0
list->capacity = capacity; //传入的容量大小值
3.销毁顺序表
将list中的元素直接删除,使用delete关键字
void destroyList(seqlist* list) {
delete[]list->elements;
}
4.获取顺序表大小
函数直接返回顺序表list的size变量
int sizeList(seqlist* list) {
return list->size;
}
5.判断顺序表是否为空
将上面返回的size值进行判断是否为0
bool isEmpty(seqlist* list) {
return list->size == 0;
}
6.插入新元素
首先判断输入的index的合法性,须在size范围内;
如果顺序表的空间大小不够,对其进行扩容,申请新的容量,使其capacity更大;遍历旧列表中的元素并赋值给新列表,删除旧列表中的元素;
从最后一位元素向前遍历,将元素后移一位,顺序表size加1
void insert(seqlist* list, int index, eleType element) {
//判断输入合法性
if (index <0 || index>list->size)
throw std::invalid_argument("Invalid index");
//内存扩容*2
if (list->size == list->capacity) {
int newcapacity = list->capacity * 2;
eleType* newElements = new eleType[newcapacity];
for (int i = 0; i < list->size; i++) {
newElements[i] = list->elements[i];
}
delete[]list->elements; //删除旧元素
list->elements = newElements;
list->capacity = newcapacity;
}
for (int i = list->size; i > index;i--) { //从最后一位向前遍历
list->elements[i] = list->elements[i - 1];
}
list->elements[index] = element;
list->size++;
}
7.删除元素
同理,先检查序号index合法性;
从输入的index开始向最后一位(size)遍历,将每一位前移一位;
size减1
void deleteElement(seqlist* list, int index) {
if (index <0 || index>=list->size)
throw std::invalid_argument("Invalid index");
for (int i = index; i < list->size - 1; i++) {
list->elements[i] = list->elements[i + 1];
}
list->size--;
}
8.查找元素下标
输入元素值后遍历列表,直到查找到列表元素与其相等,返回列表元素的下标
int findElement(seqlist* list, eleType element) {
for (int i = 0; i < list->size; i++) {
if (list->elements[i] == element)
return i;
}
return -1;
}
9.元素索引
同样的,索引也需要检查下标的合法性,函数返回元素值
eleType getElement(seqlist* list, int index) {
if (index < 0 || index >= list->size)
throw std::invalid_argument("Invalid index");
return list->elements[index];
}
10.元素修改
与索引结合,将上面查找到的元素用新元素值替代即可实现元素修改
void updateElement(seqlist* list, int index, eleType value) {
if (index < 0 || index >= list->size)
throw std::invalid_argument("Invalid index");
list->elements[index] = value;
}
【运行结果】
在主函数中先创建一个顺序表mylist,将其初始化;
循环插入元素1-9,输出其内存大小,并判断其是否为空
int main() {
seqlist mylist;
initializeList(&mylist, 10);
for (int i = 0; i < 10; i++)
insert(&mylist, i, i * 10);
cout << "size:" << sizeList(& mylist) << endl;
cout << "Isempty" << isEmpty(&mylist);
}
看完上面的介绍,发现想要实现顺序表的各种功能代码任务量较大,那么可以使用C++STL库中的vector容器实现
【代码解析】
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> list = { 1,2,3,4,5,6 };
cout <<"size:"<< list.size()<<endl;
list.push_back(7);
for (int i = 0; i <= 7; i++)
{
cout << list[i] << " ";
}
}
创建容器
vector<int> list ={1,2,3,4,5,6}
<>中为容器的类型,list为容器的名称,{}中为初始元素
容器中的全部元素
list.size()
插入元素
list.push_back(7)
()中的值为插入元素的大小
元素索引
list[i]
【运行结果】
【总结】
顺序表是十分常用的数据结构,俗称列表,使用现成的库可以减少大量的代码量,但如果要实现多种功能还是需要自己创建列表的结构体与各种列表函数