列表是一种抽象的数据结构,表示元素的有序集合。列表可以基于数组或者链表实现。
当使用数组实现列表时,长度不可变的性质会导致列表的实用性降低。为解决此问题,我们可以使用「动态数组 dynamic array」来实现列表。即C++ 中的 vector。
1. 初始化列表
初始化有两种方式,一种无初值初始化,另一种有初值初始化。
//列表初始化
//无初值初始化
vector<int> nums1;
//有初值初始化
vector<int> nums={1,2,3,4};
2. 访问和更新元素
当使用数组来实现列表时,本质上就是访问和更新对应的数组元素。效率高,时间复杂度O(n)
//列表元素的访问与更新
//访问下标为1的元素
int num = nums[1];
//更新元素
nums[2] = 5;
3. 插入和删除元素
列表尾部插入和删除元素时间复杂度O(1),其他地方时间复杂度为O(n)。
//列表元素插入与删除
//清空列表
nums.clear();
//在列表尾部插入元素
nums.push_back(1);
nums.push_back(3);
nums.push_back(9);
//在中间插入元素
nums.insert(nums.begin()+3,8);//下标3的位置插入8;
//删除中间元素
nums.erase(nums.begin()+3);//删除索引3的元素
4. 遍历列表
和数组遍历一样,采用索引遍历。也可以直接遍历。
//遍历列表
//索引遍历
for(int i=0;i<nums.size();i++){
cout<<nums[i]<<endl;
}
//直接遍历元素
for(int num:nums){
cout<<num<<endl;
}
5.拼接列表
可将新列表直接拼接到原列表后面。
//拼接列表
vector<int> nums2={9,3,4,5,7};
//将nums2拼接到nums后
nums.insert(nums.end(),nums2.begin(),nums2.end());
6.排序列表
//列表排序
sort(nums.begin(),nums.end());//默认升序排列
7.链表具体实现(数组)
C++内置了列表,源码实现较为复杂,下面使用数组实现一个简易的列表。包含三个重点设计,
初始容量:选取一个合适的初始容量,本次选择10.
数量记录:声明一个size用于记录当前元素个数,随着删除和添加元素实时更新。
扩容机制:若插入元素时列表容量已满,则需要进行扩容,规定每次扩容至原来的两倍。
//列表实现
class MyList{
private:
int *arr;//数组(存储列表元素)
int arrCapacity = 10;//初始容量是10
int arrSize=0;//记录当前元素个数
int extendRatio=2;//每次扩展的倍数
public:
//构造函数
MyList(){
arr=new int[arrCapacity];
}
//析构函数
~MyList(){
delete[] arr;
}
//获取当列表元素个数
int size(){
return arrSize;
}
//获取列表容量
int capacity(){
return arrCapacity;
}
//访问索引为index的元素
int get(int index){
if(index<0||index>=arrSize) throw out_of_range("索引越界");
else
return arr[index];
}
//更新元素
void set(int index, int num){
if(index<0||index>=arrSize) throw out_of_range("索引越界");
arr[index]=num;
}
//在尾部添加元素
void add(int num){
if(size()==capacity()) extendCapacity();
arr[size()]=num;
arrSize++;
}
//在中间插入元素
void insert(int index, int num){
if(index<0||index>=arrSize) throw out_of_range("索引越界");
if(size()==capacity()) extendCapacity();//元素个数超出容量,触发扩容机制
for(int j=size(); j>=index; j--){
arr[j+1]=arr[j];
}
arr[index]=num;
arrSize++;//更新元素数量
}
int remove(int index){
if(index<0||index>=arrSize) throw out_of_range("索引越界");
int num=arr[index];//y用于后面要返回删除的元素
for(int j=index;j<size()-1;j++){
arr[j]=arr[j+1];
}
arrSize--;//更新元素数量
return num;
}
//扩容列表
void extendCapacity(){
int* tmp = arr;//保存当前列表地址,用于后面删除原列表空间
arr =new int[capacity()*extendRatio];
//将源列表中的元素复制到新列表中
for(int i=0;i<size();i++){
arr[i]=tmp[i];
}
//释放内存
delete[ ] tmp;
arrCapacity=capacity()*extendRatio;//新的容量更新
}
//将列表转换为Vector数组用于打印
vector<int> toVector(){
vector<int> vc(size());
for(int i=0; i<size();i++){
vc[i]=arr[i];
}
return vc;
}
};
声明:本人所写内容全部参考hello-algo,仅用于个人复习。