当前位置: 首页 > news >正文

数据结构(动态数组)

 一、基本特性

属性说明
内存连续数组在内存中占据一段连续空间,便于地址偏移计算
支持随机访问可通过下标 array[i] 在常数时间 O(1) 读取或写入数据
可扩容静态数组大小固定,动态数组支持扩容
类型一致性所有元素必须是相同类型

 二、优、缺点

 优点:

  1. 访问效率高:支持通过下标快速访问元素,时间复杂度为 O(1)
  2. 尾部添加/删除效率高(动态数组):push_back()pop_back() 操作时间复杂度为 O(1)(均摊)

 缺点:

  1. 插入/删除(非尾部)代价大:需要移动大量元素,时间复杂度为 O(n)
  2. 扩容代价高:如果数组满了需要扩容,通常按1.5 或 2倍扩容策略,会发生一次 O(n) 拷贝操作

三、典型操作复杂度分析

操作类型时间复杂度
下标访问O(1)
尾部插入O(1)(均摊)
尾部删除O(1)
插入指定位置O(n)
删除指定位置O(n)
查找(无序)O(n)
查找(二分,有序)O(log n)

四、动态数组类实现详解

功能列表:

  • 支持动态扩容

  • 支持拷贝构造函数、拷贝赋值运算符、移动构造函数、移动赋值运算符

  • 支持 push_backpop_backinserterase

  • 支持查找、访问、容量大小获取

  • 支持 [] 运算符重载访问元素

template<typename T>
class Array {
public:// 构造函数Array(int capacity = 10): m_size(0), m_capacity(capacity){m_pArr = new T[m_capacity];}// 拷贝构造函数Array(const Array& other): m_size(other.m_size), m_capacity(other.m_capacity){m_pArr = new T[m_capacity];for (int i = 0; i < m_size; ++i) {m_pArr[i] = other.m_pArr[i];}}// 拷贝赋值运算符Array& operator=(const Array& other) {if (this == &other) return *this;delete[] m_pArr;m_capacity = other.m_capacity;m_size = other.m_size;m_pArr = new T[m_capacity];for (int i = 0; i < m_size; ++i) {m_pArr[i] = other.m_pArr[i];}return *this;}// 移动构造函数Array(Array&& other) noexcept: m_size(other.m_size),m_capacity(other.m_capacity),m_pArr(other.m_pArr){other.m_pArr = nullptr;other.m_size = 0;other.m_capacity = 0;}// 移动赋值运算符Array& operator=(Array&& other) noexcept {if (this == &other) return *this;delete[] m_pArr;m_size = other.m_size;m_capacity = other.m_capacity;m_pArr = other.m_pArr;other.m_pArr = nullptr;other.m_size = 0;other.m_capacity = 0;return *this;}// 析构函数~Array() {delete[] m_pArr;m_pArr = nullptr;}// 尾部添加元素void push_back(const T& val) {if (m_size == m_capacity) {expand(2 * m_capacity);}m_pArr[m_size++] = val;}// 原地构造对象(避免额外拷贝)template<typename... Args>void emplace_back(Args&&... args) {if (m_size == m_capacity) {expand(2 * m_capacity);}new (m_pArr + m_size) T(std::forward<Args>(args)...);++m_size;}// 删除尾部元素void pop_back() {if (m_size > 0) {m_size--;}}// 插入元素到指定位置void insert(int pos, const T& val) {if (pos < 0 || pos > m_size) {throw std::out_of_range("insert: out of range");}if (m_size == m_capacity) {expand(m_capacity == 0 ? 1 : 2 * m_capacity);}for (int i = m_size - 1; i >= pos; --i) {m_pArr[i + 1] = m_pArr[i];}m_pArr[pos] = val;m_size++;}// 删除指定位置的元素void erase(int pos) {if (pos < 0 || pos >= m_size) {throw std::out_of_range("erase: out of range");}for (int i = pos; i < m_size - 1; ++i) {m_pArr[i] = m_pArr[i + 1];}m_size--;}// 查找某个元素,返回下标,不存在返回 -1int find(const T& val) const {for (int i = 0; i < m_size; ++i) {if (m_pArr[i] == val) {return i;}}return -1;}// 预留容量void reserve(int newCapacity) {if (newCapacity > m_capacity) {expand(newCapacity);}}// 清空元素void clear() {m_size = 0;}// 判空bool empty() const {return m_size == 0;}// 获取数组大小int size() const {return m_size;}// 获取数组容量int capacity() const {return m_capacity;}// 访问首尾元素T& front() {if (empty()) throw std::out_of_range("front(): array is empty");return m_pArr[0];}T& back() {if (empty()) throw std::out_of_range("back(): array is empty");return m_pArr[m_size - 1];}// 下标访问元素(非 const)T& operator[](int pos) {if (pos < 0 || pos >= m_size) {throw std::out_of_range("operator[]: out of range");}return m_pArr[pos];}// 下标访问元素(const 版本)const T& operator[](int pos) const {if (pos < 0 || pos >= m_size) {throw std::out_of_range("operator[]: out of range");}return m_pArr[pos];}// 支持范围 for 循环(const)const T* begin() const { return m_pArr; }const T* end() const { return m_pArr + m_size; }// 非 const 版本迭代器T* begin() { return m_pArr; }T* end() { return m_pArr + m_size; }private:// 扩容方法void expand(int newCapacity) {T* newArr = new T[newCapacity];for (int i = 0; i < m_size; ++i) {newArr[i] = m_pArr[i];}delete[] m_pArr;m_pArr = newArr;m_capacity = newCapacity;}private:int m_size;       // 当前元素个数int m_capacity;   // 当前容量T* m_pArr;        // 数组首地址
};

http://www.dtcms.com/a/303374.html

相关文章:

  • PyTorch中flatten()函数详解以及与view()和 reshape()的对比和实战代码示例
  • DevOps时代的知识治理革命:Wiki如何成为研发效能的新引擎
  • GPT Agent与Comet AI Aent浏览器对比横评
  • Anaconda创建环境报错:CondaHTTPEFTOT: HTTP 403 FORBIDDEN for url
  • 力扣 之 最小覆盖子串(变长滑动窗口,越短越好)
  • 推客系统全链路架构设计与高并发实践:从CPS分佣到社交裂变
  • ARM双频RFID读写系统的设计
  • 【快捷指令】ios/macos快捷指令如何调用api接口(json请求例子)
  • 从“数字鸿沟”到“数字红利”:智慧养老如何让老人跨越技术门槛
  • MBR和GPT分区的区别
  • C语言-数组:数组(定义、初始化、元素的访问、遍历)内存和内存地址、数组的查找算法和排序算法;
  • 导入Maven项目
  • 解决幻读问题
  • maven 打包报错 process terminated
  • 基于Spring Boot+Vue的吉他社团系统设计和实现(协同过滤算法)
  • 架构师增效指南:飞算JavaAI:需求驱动下的智能微服务拆分与治理
  • 五自由度磁悬浮轴承转子不平衡质量的高性能控制策略全解析
  • 亚马逊地址关联暴雷:新算法下的账号安全保卫战
  • 采用黑翅鸢优化算法BKA-CNN-LSTM、CNN-LSTM、LSTM、CNN四模型多变量回归预测,多输入单输出(Matlab)
  • 《计算机“十万个为什么”》之 [特殊字符] 序列化与反序列化:数据打包的奇妙之旅 ✈️
  • Python与Mysql
  • Error: Unable to find a match: python3.8
  • FDWS86068-F085高频开关电源DC/DC转换器,适合高功率密度N沟道增强型
  • 7月28号打卡
  • 为什么额前的头发叫刘海,不叫张海
  • Linux 下安装包安装lsof工具
  • 基础算法(9)——哈希表
  • nginx日志分割
  • 11.Dockerfile简介
  • Java中的协变、逆变