类结构
后续提供的访问接口的其序号范围使用的是[1,n]
class CArrayList{
public:
//数组列表
ElemType *data;
//容量
int MaxSize;
//长度
int length;
};
顺序表是动态数组,其容量是可变的,相比数组来说更加灵活,但需要程序员自己维护其空间。
与数组类似,支持随机存取,其访问效率较高复杂度为O(1),但是如果要插入或删除元素需要移动大量元素故时间复杂度是O(n)。
构造和析构
//构造函数
CArrayList::CArrayList(){
this->MaxSize = InitSize;
this->length = 0;
this->data = new ElemType[InitSize];
}
//析构函数
CArrayList::~CArrayList(){
delete[] this->data;
}
- initSize 是宏定义的常量,作为空间的起始大小。
- 用new的方式来开辟空间可以使空间开辟在堆上,防止构造函数结束时被销毁
- 析构函数只需要将data指向的连续空间销毁即可
支持的一些方法
/***
功能:插入元素,在第i个位置插入元素e
参数:L:待插入列表
i:插入位置
e:插入元素
***/
bool CArrayList::ListInsert(int i,ElemType e){
//位置无效处理
if(i<1||i>this->length+1){
std::cout<<"插入位置无效"<<std::endl;
return false;
}
//空间不足处理
if(this->length>=this->MaxSize){
std::cout<<"列表已分配空间不足"<<std::endl;
return false;
}
//后续元素向后移动
for(int j=this->length;j>=i;j--){
this->data[j]=this->data[j-1];
}
//元素插入指定位置
this->data[i-1]=e;
//长度自增
this->length++;
return true;
}
/***
功能:删除指定元素,并用e接受删除的元素
参数:i:待删除元素的位置
e:接受待删除元素的值
***/
bool CArrayList::ListDelete(int i,ElemType &e){
//位置无效处理
if(i<1||i>this->length){
std::cout<<"删除位置无效"<<std::endl;
return false;
}
e = this->data[i-1];
for(int j = i;j<this->length;j++){
this->data[i-1]=this->data[i];
}
this->length--;
return true;
}
/***
功能:找到指定值的元素的位置,若不存在则返回0
参数:e:查找的值
***/
int CArrayList::LocateElem(ElemType e){
int i;
for(i=0;i<this->length;i++){
if(this->data[i]==e){
return i+1;
}
}
return 0;
}
//打印列表中的元素
void CArrayList::Print(){
if(this->length == 0){
std::cout<<"[]"<<std::endl;
return;
}
std::cout<<"[";
for(int i=0;i<this->length-1;i++){
std::cout<<this->data[i]<<",";
}
std::cout<<this->data[this->length-1]<<"]"<<std::endl;
}
ElemType& CArrayList::operator[](int i){
return this->data[i-1];
}
遇到的坑
在使用引用的时候,函数值使用了引用返回,用一个变量接收。这个过程会进行一次拷贝构造。需要用引用接受才能正确接受到函数内部new出来的对象
总结
顺序表是线性表的顺序存储。它用一组连续的存储单元依次存储线性表中的数据元素,它使得逻辑上相邻的两个元素在物理位置上也相邻。由于其物理位置相邻的特性,每个元素的起始位置均与第一个元素相差一个与位序成正比的常数。故可以通过起始位置和位序以及元素所占的空间大小计算出任意一个元素的位置,即支持随机存取。它适用于有大量访问元素操作的场景。