数据结构整理-列表篇

本文详细介绍了C++中列表(如vector)的数据结构概念,以及如何通过数组和链表实现。涵盖了初始化、元素访问与更新、插入与删除、遍历、拼接、排序等操作,并对比了C++内置列表与自定义链表的实现。
摘要由CSDN通过智能技术生成

列表是一种抽象的数据结构,表示元素的有序集合。列表可以基于数组或者链表实现。

当使用数组实现列表时,长度不可变的性质会导致列表的实用性降低。为解决此问题,我们可以使用「动态数组 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,仅用于个人复习。

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值