1-5 列表:数组实现(todo)

一、列表的基本概念

什么是基于数组的列表

列表是使用连续内存空间存储元素的线性数据结构。 列表一般采用两种方式实现, 一种是数组, 一种是链表, 本节使用数组实现。

给定一个数组arr[],根据该数组创建链表。示例:

输入: arr[] = [1, 2, 3, 4, 5]
输出: 1 -> 2 -> 3 -> 4 -> 5
说明: 给定 arr[],链表表示为
image


二、基于数组的列表的实现

编号 函数名 简短功能 时间复杂度 空间复杂度
2.1 构造函数
析构函数
默认构造:创建空列表
带参构造:指定初始容量
析构函数:释放动态数组
O(1)
O(n)
O(1)
O(1)
O(n)
O(1)
2.2 pushBack 在列表尾部添加元素,容量不足时自动翻倍扩容 O(1) 均摊 O(1)
2.3 insert 在指定位置插入元素,该位置及之后元素后移 O(n) O(1)
2.4 popBack 删除尾部元素,仅减少计数不释放内存 O(1) O(1)
2.5 remove 删除指定位置元素,该位置之后元素前移 O(n) O(1)
2.6 removeByValue 查找并删除第一个匹配元素 O(n) O(1)
2.7 operator[]
at
front
back
下标访问(无检查)
安全访问(有检查)
访问首元素
访问尾元素
O(1)
O(1)
O(1)
O(1)
O(1)
O(1)
O(1)
O(1)
2.8 reserve
resize
shrinkToFit
clear
预分配空间
调整逻辑大小
缩容至实际大小
清空列表
O(n)
O(n)
O(n)
O(1)
O(n)
O(n)
O(n)
O(1)
2.9 find
contains
线性查找元素索引
判断是否包含元素
O(n)
O(n)
O(1)
O(1)
2.10 拷贝构造
拷贝赋值
移动构造
移动赋值
深拷贝构造
深拷贝赋值
转移资源所有权
转移资源所有权
O(n)
O(n)
O(1)
O(1)
O(n)
O(n)
O(1)
O(1)
2.11 begin
end
返回指向首元素的指针
返回指向尾后元素的指针
O(1)
O(1)
O(1)
O(1)
2.12 print 输出列表所有元素及容量信息 O(n) O(1)

2.1 构造函数与析构函数

设计要点

  • 默认构造:创建空列表,容量为0
  • 带形参构造:指定初始容量,预分配内存
  • 析构函数:释放动态分配的数组内存
template <typename T>
class ArrayList 
{
private:
    T* m_data;           // 存储元素的动态数组
    int m_capacity;      // 当前容量(总空间)
    int m_currentSize;   // 当前元素个数

public:
    // 默认构造函数
    ArrayList() 
        : m_data(nullptr), m_capacity(0), m_currentSize(0) 
    {
    }
    
    // 指定初始容量
    explicit ArrayList(int initialCapacity) 
        : m_capacity(initialCapacity), m_currentSize(0) 
    {
        if (initialCapacity < 0) 
        {
            throw std::invalid_argument("Capacity cannot be negative");
        }
        m_data = new T[m_capacity];
    }
    
    // 析构函数
    ~ArrayList() 
    {
        delete[] m_data;
    }
};

2.2 尾部添加操作 (pushBack)

设计要点

  • 检查容量,不足时触发扩容
  • 扩容策略:容量翻倍(均摊O(1))
  • 在数组末尾添加新元素

可视化演示

初始: [_, _, _, _]  capacity=4, size=0
pushBack(10): [10, _, _, _]  size=1
pushBack(20): [10, 20, _, _]  size=2
pushBack(30): [10, 20, 30, _]  size=3
pushBack(40): [10, 20, 30, 40]  size=4
pushBack(50): 触发扩容
              创建新数组 [_, _, _, _, _, _, _, _] capacity=8
              复制数据  [10, 20, 30, 40, _, _, _, _]
              添加50    [10, 20, 30, 40, 50, _, _, _] size=5

代码实现

// 在尾部添加元素
void pushBack(const T& value) 
{
    // 检查是否需要扩容
    if (m_currentSize == m_capacity) 
    {
        // 扩容策略:如果容量为0则设为1,否则翻倍
        int newCapacity = (m_capacity == 0) ? 1 : m_capacity * 2;
        resize(newCapacity);
    }
    m_data[m_currentSize++] = value;
}

// 扩容辅助函数
void resize(int newCapacity) 
{
    T* newData = new T[newCapacity];
    
    // 复制旧数据到新数组
    for (int i = 0; i < m_currentSize; i++) 
    {
        newData[i] = m_data[i];
    }
    
    delete[] m_data;
    m_data = newData;
    m_capacity = newCapacity;
}

2.3 指定位置插入 (insert)

设计要点

  • 检查索引合法性(0 ≤ index ≤ size)
  • 容量不足时先扩容
  • 将插入位置后的元素统一后移一位

可视化演示:比如在B位置插入X

初始: [A, B, C, D, _, _]  size=4, capacity=6
insert(1, X):
  1. 检查index=1合法
  2. 检查容量充足
  3. 元素后移:
     i=4: [A, B, C, D, D, _]  D后移
     i=3: [A, B, C, C, D, _]  C后移
     i=2: [A, B, B, C, D, _]  B后移
     i=1: 停止
  4. 插入X: [A, X, B, C, D, _]
  5. size=5

代码实现

// 在指定位置插入元素
void insert(int index, const T& value) 
{
    if (index < 0 || index > m_currentSize) {
        throw std::out_of_range("Insert index out of range");
    }
    
    // 检查容量
    if (m_currentSize == m_capacity) {
        int newCapacity = (m_capacity == 0) ? 1 : m_capacity * 2;
        resize(newCapacity);
    }
    
    // 将index及之后的元素后移
    for (int i = m_currentSize; i > index; i--) {
        m_data[i] = m_data[i - 1];
    }
    
    m_data[index] = value;
    m_currentSize++;
}

2.4 尾部删除 (popBack)

设计要点

  • 检查列表非空
  • 仅减少计数,不实际释放内存(由析构函数统一处理)
  • 不自动缩容

可视化演示

初始: [A, B, C, D]  size=4
popBack():
  size减1 → [A, B, C, D] (逻辑上视为 [A, B, C])
  
再次popBack():
  size减1 → [A, B, C, D] (逻辑上视为 [A, B])

代码实现

// 删除尾部元素
void popBack() 
{
    if (isEmpty()) 
    {
        throw std::runtime_error("Cannot pop from empty list");
    }
    m_currentSize--;  // 只需减少计数
}

2.5 指定位置删除 (remove)

设计要点

  • 检查索引合法性
  • 将删除位置后的元素统一前移一位
  • 覆盖被删除元素

可视化演示

初始: [A, B, C, D, E]  size=5
remove(1): 删除B
  i=1: [A, C, C, D, E]  C前移覆盖B
  i=2: [A, C, D, D, E]  D前移
  i=3: [A, C, D, E, E]  E前移
  size=4 → 逻辑上 [A, C, D, E]

代码实现

// 删除指定位置元素
void remove(int index) 
{
    checkIndex(index);
    
    // 将index之后的元素前移
    for (int i = index; i < m_currentSize - 1; i++) {
        m_data[i] = m_data[i + 1];
    }
    m_currentSize--;
}

// 索引检查辅助函数
void checkIndex(int index) const 
{
    if (index < 0 || index >= m_currentSize) 
    {
        throw std::out_of_range("Index out of range: " + std::to_string(index));
    }
}

2.6 按值删除 (removeByValue)

设计要点

  • 遍历查找第一个匹配元素
  • 调用remove删除该元素
  • 返回是否成功删除

可视化演示

初始状态: [10, 20, 30, 20, 40]  m_currentSize=5

调用: removeByValue(20)

─────────────────────────────────────────────────────────
  i=0: m_data[0]=10
        10 == 20 ? 否 → 继续循环
        列表状态: [10, 20, 30, 20, 40]
─────────────────────────────────────────────────────────
  i=1: m_data[1]=20
        20 == 20 ? 是 → 找到匹配
        调用 remove(1)

        remove(1) 执行过程:
        ─ 检查索引: 1 >=0 且 1 < 5 ✓
        ─ 元素前移:
             i=1: m_data[1]=m_data[2] → [10, 30, 30, 20, 40]
             i=2: m_data[2]=m_data[3] → [10, 30, 20, 20, 40]
             i=3: m_data[3]=m_data[4] → [10, 30, 20, 40, 40]
        ─ m_currentSize-- → 4

        remove(1) 返回后: [10, 30, 20, 40]  size=4
        return true
─────────────────────────────────────────────────────────

最终结果: [10, 30, 20, 40]  m_currentSize=4
          只删除了第一个匹配的20(原索引1)
          第二个20(原索引3,现索引2)保留

代码实现

// 查找并删除第一个匹配元素
bool removeByValue(const T& value) 
{
    for (int i = 0; i < m_currentSize; i++) {
        if (m_data[i] == value) {
            remove(i);
            return true;
        }
    }
    return false;
}

2.7 元素访问操作

设计要点

  • operator[]:快速访问,无边界检查
  • at():安全访问,有边界检查
  • front() / back():访问首尾元素

代码实现

// 下标访问(无边界检查)
T& operator[](int index) 
{
    return m_data[index];
}

const T& operator[](int index) const 
{
    return m_data[index];
}

// 安全访问(有边界检查)
T& at(int index) 
{
    checkIndex(index);
    return m_data[index];
}

const T& at(int index) const 
{
    checkIndex(index);
    return m_data[index];
}

// 访问首尾元素
T& front() 
{
    if (isEmpty()) {
        throw std::runtime_error("List is empty");
    }
    return m_data[0];
}

T& back() 
{
    if (isEmpty()) {
        throw std::runtime_error("List is empty");
    }
    return m_data[m_currentSize - 1];
}

2.8 容量管理操作

设计要点

  • reserve:预分配空间,避免多次扩容
  • resize:调整逻辑大小
  • shrinkToFit:释放多余内存

代码实现

// 预分配空间
void reserve(int newCapacity) 
{
    if (newCapacity > m_capacity) {
        resize(newCapacity);
    }
}

// 调整大小
void resize(int newSize) 
{
    if (newSize > m_capacity) {
        reserve(newSize);
    }
    m_currentSize = newSize;
}

// 释放多余内存
void shrinkToFit() 
{
    if (m_currentSize < m_capacity) {
        resize(m_currentSize);
    }
}

// 清空列表
void clear() 
{
    m_currentSize = 0;
}

// 查询接口
int size() const 
{ 
    return m_currentSize; 
}

int getCapacity() const 
{ 
    return m_capacity; 
}

bool isEmpty() const 
{ 
    return m_currentSize == 0; 
}

2.9 查找操作

设计要点

  • find:线性查找,返回索引或-1
  • contains:判断是否包含某元素

代码实现

// 线性查找
int find(const T& value) const 
{
    for (int i = 0; i < m_currentSize; i++) {
        if (m_data[i] == value) {
            return i;
        }
    }
    return -1;
}

// 判断是否包含
bool contains(const T& value) const 
{
    return find(value) != -1;
}

2.10 拷贝控制

设计要点

  • 拷贝构造:深拷贝,复制所有元素
  • 拷贝赋值:异常安全实现
  • 移动构造/赋值:转移资源所有权

代码实现

// 拷贝构造函数(深拷贝)
ArrayList(const ArrayList& other) 
    : m_capacity(other.m_capacity), m_currentSize(other.m_currentSize) 
{
    m_data = new T[m_capacity];
    for (int i = 0; i < m_currentSize; i++) {
        m_data[i] = other.m_data[i];
    }
}

// 拷贝赋值运算符
ArrayList& operator=(const ArrayList& other) 
{
    if (this != &other) {
        T* newData = new T[other.m_capacity];
        for (int i = 0; i < other.m_currentSize; i++) {
            newData[i] = other.m_data[i];
        }
        
        delete[] m_data;
        m_data = newData;
        m_capacity = other.m_capacity;
        m_currentSize = other.m_currentSize;
    }
    return *this;
}

// 移动构造函数
ArrayList(ArrayList&& other) noexcept
    : m_data(other.m_data), m_capacity(other.m_capacity), m_currentSize(other.m_currentSize) 
{
    other.m_data = nullptr;
    other.m_capacity = 0;
    other.m_currentSize = 0;
}

// 移动赋值运算符
ArrayList& operator=(ArrayList&& other) noexcept 
{
    if (this != &other) {
        delete[] m_data;
        m_data = other.m_data;
        m_capacity = other.m_capacity;
        m_currentSize = other.m_currentSize;
        other.m_data = nullptr;
        other.m_capacity = 0;
        other.m_currentSize = 0;
    }
    return *this;
}

2.11 迭代器支持

设计要点

  • 提供begin/end指针,支持范围for循环
  • 支持STL算法

代码实现

// 迭代器支持
T* begin() 
{ 
    return m_data; 
}

T* end() 
{ 
    return m_data + m_currentSize; 
}

const T* begin() const 
{ 
    return m_data; 
}

const T* end() const 
{ 
    return m_data + m_currentSize; 
}

2.12 辅助函数

// 输出列表内容
void print() const 
{
    std::cout << "[";
    for (int i = 0; i < m_currentSize; i++) {
        std::cout << m_data[i];
        if (i < m_currentSize - 1) {
            std::cout << ", ";
        }
    }
    std::cout << "] (size=" << m_currentSize << ", capacity=" << m_capacity << ")\n";
}

2.x 基于数组的列表的完整实现

#include <iostream>
#include <stdexcept>
#include <algorithm>

template <typename T>
class ArrayList {
private:
    T* m_data;           // 存储元素的动态数组
    int m_capacity;      // 当前容量(总空间)
    int m_currentSize;   // 当前元素个数

    // 扩容函数:当空间不足时调用
    void resize(int newCapacity) {
        // 创建新数组
        T* newData = new T[newCapacity];
        
        // 复制旧数据到新数组
        for (int i = 0; i < m_currentSize; i++) {
            newData[i] = m_data[i];
        }
        
        // 释放旧内存
        delete[] m_data;
        
        // 更新指针和容量
        m_data = newData;
        m_capacity = newCapacity;
    }

    // 检查索引是否合法
    void checkIndex(int index) const {
        if (index < 0 || index >= m_currentSize) {
            throw std::out_of_range("Index out of range: " + std::to_string(index));
        }
    }

public:
    // ==================== 构造函数与析构函数 ====================
    
    // 默认构造函数
    ArrayList() 
        : m_data(nullptr), m_capacity(0), m_currentSize(0) 
    {
    }
    
    // 指定初始容量
    explicit ArrayList(int initialCapacity) 
        : m_capacity(initialCapacity), m_currentSize(0) 
    {
        if (initialCapacity < 0) {
            throw std::invalid_argument("Capacity cannot be negative");
        }
        m_data = new T[m_capacity];
    }
    
    // 析构函数
    ~ArrayList() {
        delete[] m_data;
    }
    
    // ==================== 拷贝控制 ====================
    
    // 拷贝构造函数(深拷贝)
    ArrayList(const ArrayList& other) 
        : m_capacity(other.m_capacity), m_currentSize(other.m_currentSize) 
    {
        m_data = new T[m_capacity];
        for (int i = 0; i < m_currentSize; i++) {
            m_data[i] = other.m_data[i];
        }
    }
    
    // 拷贝赋值运算符
    ArrayList& operator=(const ArrayList& other) {
        if (this != &other) {  // 防止自赋值
            // 复制并交换(异常安全)
            T* newData = new T[other.m_capacity];
            for (int i = 0; i < other.m_currentSize; i++) {
                newData[i] = other.m_data[i];
            }
            
            delete[] m_data;
            m_data = newData;
            m_capacity = other.m_capacity;
            m_currentSize = other.m_currentSize;
        }
        return *this;
    }
    
    // 移动构造函数(C++11)
    ArrayList(ArrayList&& other) noexcept
        : m_data(other.m_data), m_capacity(other.m_capacity), m_currentSize(other.m_currentSize) 
    {
        other.m_data = nullptr;
        other.m_capacity = 0;
        other.m_currentSize = 0;
    }
    
    // 移动赋值运算符
    ArrayList& operator=(ArrayList&& other) noexcept {
        if (this != &other) {
            delete[] m_data;
            m_data = other.m_data;
            m_capacity = other.m_capacity;
            m_currentSize = other.m_currentSize;
            other.m_data = nullptr;
            other.m_capacity = 0;
            other.m_currentSize = 0;
        }
        return *this;
    }

    // ==================== 基本操作 ====================
    
    // 在尾部添加元素
    void pushBack(const T& value) {
        // 检查是否需要扩容
        if (m_currentSize == m_capacity) {
            // 扩容策略:如果容量为0则设为1,否则翻倍
            int newCapacity = (m_capacity == 0) ? 1 : m_capacity * 2;
            resize(newCapacity);
        }
        m_data[m_currentSize++] = value;
    }
    
    // 在指定位置插入元素
    void insert(int index, const T& value) {
        if (index < 0 || index > m_currentSize) {
            throw std::out_of_range("Insert index out of range");
        }
        
        // 检查容量
        if (m_currentSize == m_capacity) {
            int newCapacity = (m_capacity == 0) ? 1 : m_capacity * 2;
            resize(newCapacity);
        }
        
        // 将index及之后的元素后移
        for (int i = m_currentSize; i > index; i--) {
            m_data[i] = m_data[i - 1];
        }
        
        m_data[index] = value;
        m_currentSize++;
    }
    
    // 删除尾部元素
    void popBack() {
        if (isEmpty()) {
            throw std::runtime_error("Cannot pop from empty list");
        }
        m_currentSize--;  // 只需减少计数,不实际删除(析构时统一处理)
    }
    
    // 删除指定位置元素
    void remove(int index) {
        checkIndex(index);
        
        // 将index之后的元素前移
        for (int i = index; i < m_currentSize - 1; i++) {
            m_data[i] = m_data[i + 1];
        }
        m_currentSize--;
    }
    
    // 查找并删除第一个匹配元素
    bool removeByValue(const T& value) {
        for (int i = 0; i < m_currentSize; i++) {
            if (m_data[i] == value) {
                remove(i);
                return true;
            }
        }
        return false;
    }

    // ==================== 访问元素 ====================
    
    // 下标访问(无边界检查)
    T& operator[](int index) {
        return m_data[index];
    }
    
    const T& operator[](int index) const {
        return m_data[index];
    }
    
    // 安全访问(有边界检查)
    T& at(int index) {
        checkIndex(index);
        return m_data[index];
    }
    
    const T& at(int index) const {
        checkIndex(index);
        return m_data[index];
    }
    
    // 访问首尾元素
    T& front() {
        if (isEmpty()) {
            throw std::runtime_error("List is empty");
        }
        return m_data[0];
    }
    
    T& back() {
        if (isEmpty()) {
            throw std::runtime_error("List is empty");
        }
        return m_data[m_currentSize - 1];
    }

    // ==================== 容量与大小 ====================
    
    int size() const 
    { 
        return m_currentSize; 
    }
    
    int getCapacity() const 
    { 
        return m_capacity; 
    }
    
    bool isEmpty() const 
    { 
        return m_currentSize == 0; 
    }
    
    // 预分配空间(优化多次插入性能)
    void reserve(int newCapacity) {
        if (newCapacity > m_capacity) {
            resize(newCapacity);
        }
    }
    
    // 调整大小(新增元素默认初始化)
    void resize(int newSize) {
        if (newSize > m_capacity) {
            reserve(newSize);
        }
        // 如果扩大,新元素已默认构造
        // 如果缩小,只需调整计数
        m_currentSize = newSize;
    }
    
    // 清空列表(不释放内存)
    void clear() {
        m_currentSize = 0;
    }
    
    // 释放多余内存(缩容至实际大小)
    void shrinkToFit() {
        if (m_currentSize < m_capacity) {
            resize(m_currentSize);
        }
    }

    // ==================== 查找与算法 ====================
    
    // 线性查找
    int find(const T& value) const {
        for (int i = 0; i < m_currentSize; i++) {
            if (m_data[i] == value) {
                return i;
            }
        }
        return -1;  // 未找到
    }
    
    // 判断是否包含
    bool contains(const T& value) const {
        return find(value) != -1;
    }

    // ==================== 迭代器支持 ====================
    
    T* begin() 
    { 
        return m_data; 
    }
    
    T* end() 
    { 
        return m_data + m_currentSize; 
    }
    
    const T* begin() const 
    { 
        return m_data; 
    }
    
    const T* end() const 
    { 
        return m_data + m_currentSize; 
    }

    // ==================== 输出 ====================
    
    void print() const {
        std::cout << "[";
        for (int i = 0; i < m_currentSize; i++) {
            std::cout << m_data[i];
            if (i < m_currentSize - 1) {
                std::cout << ", ";
            }
        }
        std::cout << "] (size=" << m_currentSize << ", capacity=" << m_capacity << ")\n";
    }
};

三、完整功能测试

测试函数 覆盖功能点 对应章节
testBasicOperations 构造、pushBack、insert、at、front、back、operator[] 2.1, 2.2, 2.3, 2.7
testDeleteOperations remove、popBack、removeByValue、clear 2.4, 2.5, 2.6, 2.8
testFindOperations find、contains 2.9
testCapacityManagement reserve、resize、shrinkToFit、getCapacity 2.8
testIterator begin、end、范围for循环 2.11
testCopyControl 拷贝构造、拷贝赋值、移动构造、移动赋值 2.10
testExceptions 所有异常抛出场景 全章节
testEdgeCases 边界条件、大量数据、连续扩容 全章节

3.1 基本操作测试

void testBasicOperations() 
{
    std::cout << "=== 基本操作测试 ===\n";
    ArrayList<int> list;
    
    // 测试空列表状态
    assert(list.isEmpty());
    assert(list.size() == 0);
    std::cout << "Empty list created: size=" << list.size() 
              << ", isEmpty=" << list.isEmpty() << "\n";
    
    // 测试pushBack和自动扩容
    list.pushBack(10);
    list.pushBack(20);
    list.pushBack(30);
    list.print();
    assert(list.size() == 3);
    assert(list[0] == 10);
    assert(list[1] == 20);
    assert(list[2] == 30);
    std::cout << "After 3 pushBack: size=" << list.size() 
              << ", capacity=" << list.getCapacity() << "\n";
    
    // 测试insert
    list.insert(1, 15);
    list.print();
    assert(list.size() == 4);
    assert(list[1] == 15);
    std::cout << "After insert(1, 15): size=" << list.size() << "\n";
    
    // 测试访问操作
    std::cout << "Element at index 2: " << list.at(2) << "\n";
    std::cout << "Front: " << list.front() << ", Back: " << list.back() << "\n";
    assert(list.at(2) == 20);
    assert(list.front() == 10);
    assert(list.back() == 30);
    
    std::cout << "Basic operations test passed!\n\n";
}

3.2 删除操作测试

void testDeleteOperations() 
{
    std::cout << "=== 删除操作测试 ===\n";
    ArrayList<int> list;
    
    // 准备数据
    for (int i = 10; i <= 50; i += 10) {
        list.pushBack(i);
    }
    list.print();  // [10, 20, 30, 40, 50]
    assert(list.size() == 5);
    
    // 测试remove(删除中间元素)
    list.remove(1);  // 删除20
    list.print();    // [10, 30, 40, 50]
    assert(list.size() == 4);
    assert(list[1] == 30);
    std::cout << "After remove(1): size=" << list.size() << "\n";
    
    // 测试popBack
    list.popBack();  // 删除50
    list.print();    // [10, 30, 40]
    assert(list.size() == 3);
    assert(list.back() == 40);
    std::cout << "After popBack: size=" << list.size() 
              << ", back=" << list.back() << "\n";
    
    // 测试removeByValue
    bool found = list.removeByValue(30);  // 删除30
    assert(found);
    list.print();  // [10, 40]
    assert(list.size() == 2);
    assert(list[0] == 10);
    assert(list[1] == 40);
    std::cout << "After removeByValue(30): size=" << list.size() << "\n";
    
    // 测试删除不存在的值
    bool notFound = list.removeByValue(999);
    assert(!notFound);
    std::cout << "removeByValue(999) returned false as expected\n";
    
    // 测试清空
    list.clear();
    assert(list.isEmpty());
    assert(list.size() == 0);
    std::cout << "After clear: size=" << list.size() 
              << ", isEmpty=" << list.isEmpty() << "\n";
    
    std::cout << "Delete operations test passed!\n\n";
}

3.3 查找操作测试

void testFindOperations() 
{
    std::cout << "=== 查找操作测试 ===\n";
    ArrayList<int> list;
    
    list.pushBack(10);
    list.pushBack(20);
    list.pushBack(30);
    list.pushBack(40);
    list.print();
    
    // 测试find
    int idx = list.find(30);
    std::cout << "Found 30 at index: " << idx << "\n";
    assert(idx == 2);
    
    int notFound = list.find(999);
    std::cout << "Find 999 returned: " << notFound << "\n";
    assert(notFound == -1);
    
    // 测试contains
    assert(list.contains(20));
    assert(!list.contains(999));
    std::cout << "Contains 20: " << list.contains(20) << "\n";
    std::cout << "Contains 999: " << list.contains(999) << "\n";
    
    std::cout << "Find operations test passed!\n\n";
}

3.4 容量管理测试

void testCapacityManagement() 
{
    std::cout << "=== 容量管理测试 ===\n";
    
    // 测试reserve
    ArrayList<double> dlist;
    std::cout << "Initial capacity: " << dlist.getCapacity() << "\n";
    
    dlist.reserve(100);
    std::cout << "Capacity after reserve(100): " << dlist.getCapacity() << "\n";
    assert(dlist.getCapacity() >= 100);
    assert(dlist.isEmpty());  // reserve不改变size
    
    // 测试添加元素
    for (int i = 0; i < 10; i++) {
        dlist.pushBack(i * 1.5);
    }
    dlist.print();
    assert(dlist.size() == 10);
    std::cout << "After adding 10 elements: size=" << dlist.size() 
              << ", capacity=" << dlist.getCapacity() << "\n";
    
    // 测试shrinkToFit
    dlist.shrinkToFit();
    std::cout << "After shrinkToFit: capacity=" << dlist.getCapacity() << "\n";
    assert(dlist.getCapacity() == dlist.size());
    
    // 测试resize
    ArrayList<int> ilist;
    ilist.resize(20);
    std::cout << "After resize(20): size=" << ilist.size() 
              << ", capacity=" << ilist.getCapacity() << "\n";
    assert(ilist.size() == 20);
    
    // 缩小resize
    for (int i = 0; i < 20; i++) {
        ilist.pushBack(i);
    }
    ilist.resize(5);  // 缩小到5
    std::cout << "After resize to 5: size=" << ilist.size() << "\n";
    assert(ilist.size() == 5);
    
    std::cout << "Capacity management test passed!\n\n";
}

3.5 迭代器与遍历测试

void testIterator() 
{
    std::cout << "=== 迭代器测试 ===\n";
    ArrayList<int> list;
    
    for (int i = 1; i <= 5; i++) {
        list.pushBack(i * 10);
    }
    
    // 测试范围for循环
    std::cout << "Range-based for: ";
    for (const auto& elem : list) {
        std::cout << elem << " ";
    }
    std::cout << "\n";
    
    // 测试begin/end
    std::cout << "Using begin/end: ";
    for (auto it = list.begin(); it != list.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << "\n";
    
    // 测试修改迭代器指向的元素
    *list.begin() = 999;
    assert(list.front() == 999);
    std::cout << "After modify via iterator: ";
    list.print();
    
    std::cout << "Iterator test passed!\n\n";
}

3.6 拷贝控制测试

void testCopyControl() 
{
    std::cout << "=== 拷贝控制测试 ===\n";
    ArrayList<int> original;
    for (int i = 1; i <= 5; i++) {
        original.pushBack(i);
    }
    original.print();
    
    // 测试拷贝构造
    ArrayList<int> copy1 = original;
    copy1.print();
    assert(copy1.size() == original.size());
    assert(copy1[0] == original[0]);
    copy1[0] = 999;  // 修改拷贝不影响原列表
    assert(original[0] != 999);
    std::cout << "Copy constructor: original[0]=" << original[0] 
              << ", copy[0]=" << copy1[0] << "\n";
    
    // 测试拷贝赋值
    ArrayList<int> copy2;
    copy2 = original;
    assert(copy2.size() == original.size());
    copy2.print();
    std::cout << "Copy assignment test passed\n";
    
    // 测试移动构造
    ArrayList<int> temp = original;
    ArrayList<int> moved1 = std::move(temp);
    moved1.print();
    assert(moved1.size() == 5);
    // temp现在处于有效但未指定状态
    std::cout << "Move constructor test passed\n";
    
    // 测试移动赋值
    ArrayList<int> moved2;
    moved2 = std::move(moved1);
    moved2.print();
    assert(moved2.size() == 5);
    std::cout << "Move assignment test passed\n";
    
    std::cout << "Copy control test passed!\n\n";
}

3.7 异常安全测试

void testExceptions() 
{
    std::cout << "=== 异常安全测试 ===\n";
    ArrayList<int> list;
    
    // 测试空列表访问异常
    try {
        list.front();
        assert(false);  // 不应执行到这里
    } catch (const std::runtime_error& e) {
        std::cout << "front() on empty list caught: " << e.what() << "\n";
    }
    
    try {
        list.back();
        assert(false);
    } catch (const std::runtime_error& e) {
        std::cout << "back() on empty list caught: " << e.what() << "\n";
    }
    
    try {
        list.popBack();
        assert(false);
    } catch (const std::runtime_error& e) {
        std::cout << "popBack() on empty list caught: " << e.what() << "\n";
    }
    
    // 测试越界访问异常
    list.pushBack(10);
    try {
        list.at(999);
        assert(false);
    } catch (const std::out_of_range& e) {
        std::cout << "at(999) caught: " << e.what() << "\n";
    }
    
    // 测试非法插入位置
    try {
        list.insert(5, 100);  // size=1, 只能插入到0或1
        assert(false);
    } catch (const std::out_of_range& e) {
        std::cout << "insert(5) out of range caught\n";
    }
    
    // 测试非法删除位置
    try {
        list.remove(5);
        assert(false);
    } catch (const std::out_of_range& e) {
        std::cout << "remove(5) out of range caught\n";
    }
    
    // 测试负容量构造
    try {
        ArrayList<int> badList(-10);
        assert(false);
    } catch (const std::invalid_argument& e) {
        std::cout << "Negative capacity caught: " << e.what() << "\n";
    }
    
    std::cout << "Exception safety test passed!\n\n";
}

3.8 边界条件测试

void testEdgeCases() 
{
    std::cout << "=== 边界条件测试 ===\n";
    
    // 测试单元素列表
    ArrayList<int> single;
    single.pushBack(42);
    assert(single.front() == single.back());
    single.remove(0);
    assert(single.isEmpty());
    std::cout << "Single element list test passed\n";
    
    // 测试在头部和尾部插入
    ArrayList<int> list;
    list.pushBack(20);  // [20]
    list.insert(0, 10); // [10, 20] 头部插入
    list.insert(2, 30); // [10, 20, 30] 尾部插入
    list.print();
    assert(list.size() == 3);
    std::cout << "Head/tail insert test passed\n";
    
    // 测试删除头部和尾部
    list.remove(0);  // 删除头部 [20, 30]
    list.remove(1);  // 删除尾部 [20]
    list.print();
    assert(list.size() == 1);
    assert(list[0] == 20);
    std::cout << "Head/tail remove test passed\n";
    
    // 测试大量数据
    ArrayList<int> large;
    for (int i = 0; i < 10000; i++) {
        large.pushBack(i);
    }
    assert(large.size() == 10000);
    assert(large.front() == 0);
    assert(large.back() == 9999);
    std::cout << "Large data test (10000 elements) passed\n";
    
    // 测试连续扩容
    ArrayList<int> growing;
    int prevCapacity = 0;
    for (int i = 0; i < 100; i++) {
        growing.pushBack(i);
        if (growing.getCapacity() != prevCapacity) {
            std::cout << "Expanded at size=" << i 
                      << ", new capacity=" << growing.getCapacity() << "\n";
            prevCapacity = growing.getCapacity();
        }
    }
    std::cout << "Continuous expansion test passed\n";
    
    std::cout << "Edge cases test passed!\n\n";
}

3.9 主函数入口

int main() 
{
    std::cout << "========================================\n";
    std::cout << "    ArrayList Comprehensive Test Suite   \n";
    std::cout << "========================================\n\n";
    
    testBasicOperations();
    testDeleteOperations();
    testFindOperations();
    testCapacityManagement();
    testIterator();
    testCopyControl();
    testExceptions();
    testEdgeCases();
    
    std::cout << "========================================\n";
    std::cout << "    All tests passed successfully!        \n";
    std::cout << "========================================\n";
    
    return 0;
}
posted @ 2026-03-20 19:27  游翔  阅读(1)  评论(0)    收藏  举报