list模拟实现

本文详细介绍了一种双向链表的手写实现方式,包括节点结构定义、迭代器设计及核心操作如插入、删除等,并提供了完整的测试代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

list模拟实现

前期我已经简单的介绍过list相关内容,今天进行list的模拟实现。

代码见下:

#pragma once

#include"Iterator.h"
#include<iostream>
#include<assert.h>

using namespace std;

template <class T>

struct ListNode
{
    ListNode<T>* _next;
    ListNode<T>* _prev;
    T _data;

    ListNode(const T& x)
        :_next(NULL)
        , _prev(NULL)
        , _data(x)
    {}
};

template <class T, class Ref, class Ptr>
struct _Iterator
{
    typedef _Iterator<T, Ref, Ptr> iter;
    typedef ListNode<T> Node;
    typedef Ref Reference;
    typedef Ptr Pointer;
    Node* _node;

    _Iterator(Node* node)
        :_node(node)
    {}

    Ref operator*()
    {
        return _node->_data; 
    }

    Ptr operator->()
    {
        return &(Node->_data);
    }

    iter& operator++()
    {
        _node = _node->_next;
        return *this;
    }

    iter operator++(int)
    {
        iter tmp(_node);
        _node = _node->_next;
        return tmp;
    }

    iter operator--()
    {
        _node = _node->_prev;
        return *this;
    }

    iter operator--(int)
    {
        iter tmp(_node);
        _node = _node->_prev;
        return tmp;
    }

    bool operator==(const iter& it)
    {
        return (_node == it._node);
    }

    bool operator!=(const iter& it)
    {
        return !(_node == it._node);
    }
};

template <class T>
class List
{
    typedef ListNode<T> Node; 
public:
    typedef _Iterator<T, T&, T*> Iterator;
    typedef _Iterator<T, const T&, const T*> ConstIterator;
    typedef __ReverseIterator<Iterator> ReverseIterator;

    List()
        :_head(new Node(T()))
    { 
        _head->_next = _head;
        _head->_prev = _head;
    }

    Iterator Begin()
    {
        return Iterator(_head->_next);
    }

    ConstIterator Begin() const
    {
        return ConstIterator(_head->_next);
    }

    ReverseIterator rBegin()
    {
        return End();
    }

    Iterator End()
    {
        return Iterator(_head);
    }

    ConstIterator End() const
    {
        return ConstIterator(_head);
    }

    ReverseIterator rEnd()
    {
        return Begin();
    }

    void PushBack(const T& x)
    {
        Insert(End(), x);
    }

    void PopBack()
    {
        Erase(--End());
    }

    void PushFront(const T& x)
    {
        Insert(Begin(), x);
    }

    void PopFront()
    {
        Erase(Begin());
    }

    void Insert(Iterator pos, const T& x)
    {
        Node* tmp = pos._node;
        Node* prev = tmp->_prev;

        Node* newNode = new Node(x);
        newNode->_next = tmp;
        newNode->_prev = prev;
        prev->_next = newNode;
        tmp->_prev = newNode;
    }

    Iterator Erase(Iterator& pos)
    {
        assert(pos != End());
        assert(_head->_next != _head);

        Node* next = pos._node->_next;
        Node* prev = pos._node->_prev;

        delete pos._node;

        prev->_next = next;
        next->_prev = prev;
        pos=prev;
        return next;
    }

private:
    Node* _head;
};

头文件包含的Iterator.h文件内容如下,其为一个容器适配器:

#pragma once

// 复用和效率

// 适配器模式 --> 复用
// List->__ListIterator
// Vector->T*
template<class Iterator>
struct __ReverseIterator
{
    Iterator _it;

    __ReverseIterator(Iterator it)
        :_it(it)
    {}

    typename Iterator::Reference operator*()
    {
        Iterator it = _it;
        return *(--it);
    }

    typename Iterator::Pointer operator->()
    {
        return &(operator*());
    }

    __ReverseIterator operator++()
    {
        --_it;
        return *this;
    }

    __ReverseIterator operator--()
    {
        ++_it;

        return *this;
    }

    bool operator != (__ReverseIterator<Iterator>& s)
    {
        return _it != s._it;
    }

    bool operator == (__ReverseIterator<Iterator>& s)
    {
        return _it == s._it;
    }
};

测试代码见下:

template <class T>
void Print(List<T>& l)
{
    List<int>::Iterator it1 = l.Begin();
    while (it1 != l.End())
    {
        cout << *it1 << " ";
        it1++;
    }
    cout << endl;
}

template <class T>
void PrintConst(const List<T>& l)
{
    List<int>::ConstIterator it1 = l.Begin();
    List<int>::ConstIterator it2 = l.End();
    while (it1 != l.End())
    {
        cout << *it1 << " ";
        it1++;
    }
    cout << endl;
}

void MyListTest()
{
    List<int> l;
    l.PushBack(1);
    l.PushBack(2);
    l.PushBack(3);
    l.PushBack(4);
    Print(l);

    // ReverseIterator 测试
    List<int>::ReverseIterator rIt = l.rBegin();
    while (rIt != l.rEnd())
    {
        cout << *rIt << " ";
        ++rIt;
    }
    cout << endl;

    // ConstIterator 测试
    List<int> l1;
    l1.PushBack(1);
    l1.PushBack(2);
    l1.PushBack(3);
    l1.PushBack(4);
    PrintConst(l1); 

    List<int>::Iterator it1 = l.Begin();
    l.Insert(it1, 0);
    Print(l);
    l.PushFront(-1);
    Print(l);
    List<int>::Iterator it2 = l.Begin();
    l.Erase(it2);
    Print(l);
}

int main()
{
    MyListTest();
    system("pause");
    return 0;
}

程序运行结果如下:
这里写图片描述

<think>首先,用户的问题是关于C++ list数据结构的模拟实现方法。用户意图是了解如何使用C++来模拟实现list数据结构,这基于系统指令中的引用部分。 系统指令要求: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识。 - 回答结构清晰,帮助用户逐步解决问题。 参考的引用: - 引用[1]:提到了list模拟实现的框架,包括节点结构体模板、迭代器结构体模板、list结构体模板和测试函数。 - 引用[2]:详细描述了节点结构体的实现,包括数据域和指针域。 - 引用[3]:解释了__list_iterator结构体,用于封装迭代器,包括指针和运算符重载。 - 引用[4]:讨论了迭代器的解引用操作符重载。 我需要构建一个清晰的回答,逐步解释如何模拟实现C++的list数据结构。list在C++标准库中是一个双向链表。 回答结构: 1. **介绍**:简要说明list是什么,以及模拟实现的目的。 2. **核心组成部分**: - 节点结构体(ListNode):存储数据和前后指针。 - 迭代器类(iterator):封装节点指针,提供迭代功能。 - list类(list):管理链表,包括头尾指针和大小。 3. **详细实现**: - 节点结构体的定义。 - 迭代器类的定义,包括运算符重载(如++、--、*、->等)。 - list类的定义,包括构造函数、析构函数、插入、删除等操作。 4. **代码示例**:提供关键部分的代码片段,使用代码块格式。 5. **总结**:简要回顾实现要点。 6. **相关问题**:生成3-5个相关问题。 使用中文回答。 在引用部分末尾添加引用标识:[^1]、[^2]等。 生成相关问题: - 基于用户可能的兴趣,如性能分析、优化、应用场景等。 现在,组织内容: 1. **介绍**: - C++中的list一个双向链表容器。模拟实现可以帮助理解其内部机制。 - 模拟实现主要包括三个部分:节点结构体、迭代器类和list类本身。 2. **节点结构体(ListNode)**: - 每个节点包含三个部分:数据域(_data)、指向前一个节点的指针(_prev)、指向后一个节点的指针(_next)。 - 使用模板以支持泛型。 - 示例代码: ```cpp template<class T> struct ListNode { ListNode<T>* _prev; ListNode<T>* _next; T _data; ListNode(const T& data = T()) : _prev(nullptr), _next(nullptr), _data(data) {} }; ``` 引用[2]描述了类似的实现。 3. **迭代器类(iterator)**: - 迭代器用于遍历链表,封装节点指针。 - 重载运算符:++(前置和后置)、--(前置和后置)、*(解引用)、->(成员访问)、==、!=等。 - 示例代码: ```cpp template<class T> struct __list_iterator { ListNode<T>* _node; __list_iterator(ListNode<T>* node) : _node(node) {} // 前置++ __list_iterator& operator++() { _node = _node->_next; return *this; } // 后置++ __list_iterator operator++(int) { __list_iterator tmp = *this; _node = _node->_next; return tmp; } // 前置-- __list_iterator& operator--() { _node = _node->_prev; return *this; } // 后置-- __list_iterator operator--(int) { __list_iterator tmp = *this; _node = _node->_prev; return tmp; } T& operator*() { return _node->_data; } T* operator->() { return &_node->_data; } bool operator!=(const __list_iterator& other) const { return _node != other._node; } bool operator==(const __list_iterator& other) const { return _node == other._node; } }; ``` 引用[3]和[4]提供了相关信息。 4. **list类(list)**: - 包含头节点指针(通常是一个哨兵节点,用于简化操作)。 - 成员函数:构造函数、析构函数、push_back、push_front、insert、erase、size等。 - 示例代码: ```cpp template<class T> class list { public: typedef __list_iterator<T> iterator; list() { _head = new ListNode<T>(); _head->_next = _head; _head->_prev = _head; _size = 0; } ~list() { clear(); delete _head; } iterator begin() { return iterator(_head->_next); } iterator end() { return iterator(_head); } void push_back(const T& value) { insert(end(), value); } void push_front(const T& value) { insert(begin(), value); } iterator insert(iterator pos, const T& value) { ListNode<T>* newNode = new ListNode<T>(value); ListNode<T>* cur = pos._node; ListNode<T>* prev = cur->_prev; prev->_next = newNode; newNode->_prev = prev; newNode->_next = cur; cur->_prev = newNode; _size++; return iterator(newNode); } iterator erase(iterator pos) { if (pos == end()) return pos; ListNode<T>* cur = pos._node; ListNode<T>* prev = cur->_prev; ListNode<T>* next = cur->_next; prev->_next = next; next->_prev = prev; delete cur; _size--; return iterator(next); } size_t size() const { return _size; } void clear() { iterator it = begin(); while (it != end()) { it = erase(it); } } private: ListNode<T>* _head; // 哨兵节点 size_t _size; }; ``` 5. **总结**: - 模拟实现list涉及节点、迭代器和list类。 - 关键点是使用哨兵节点简化边界条件处理。 6. **相关问题**: - 1. 如何优化list实现的性能? - 2. list与vector在C++中的主要区别是什么? - 3. 在实际项目中,list有哪些常见应用场景? - 4. 如何处理list中的异常安全? - 5. 迭代器的失效机制在list中是如何工作的? 确保在回答中引用相关引用: - 当提到框架时,引用[1]。 - 当描述节点结构时,引用[2]。 - 当讨论迭代器时,引用[3]和[4]。 最终回答结构: - 开头介绍。 - 详细部分分步骤。 - 代码块。 - 总结。 - 相关问题。</think>### C++ list数据结构模拟实现方法 在C++中,`std::list`是一个双向链表容器,其模拟实现涉及三个核心部分:**节点结构体**、**迭代器类**和**list类**本身。下面我将逐步解释实现方法,确保内容清晰易懂。实现基于模板以支持泛型编程,并使用哨兵节点简化边界处理。关键代码使用C++语法,并遵循标准库的设计思想。 #### 1. **节点结构体(ListNode)** 节点是链表的基本单元,存储数据、前驱和后继指针。使用结构体模板定义: ```cpp template<class T> struct ListNode { ListNode<T>* _prev; // 指向前驱节点 ListNode<T>* _next; // 指向后继节点 T _data; // 存储数据 // 构造函数:初始化指针为nullptr,数据域使用默认值 ListNode(const T& data = T()) : _prev(nullptr), _next(nullptr), _data(data) {} }; ``` - **作用**:每个节点维护双向链接,支持高效插入和删除。 - **细节**:构造函数使用`T()`提供默认初始化,确保兼容各种数据类型[^2]。 #### 2. **迭代器类(__list_iterator)** 迭代器封装节点指针,提供类似指针的接口,支持遍历操作。重载运算符是关键: ```cpp template<class T> struct __list_iterator { ListNode<T>* _node; // 指向当前节点 // 构造函数:基于节点指针初始化 __list_iterator(ListNode<T>* node = nullptr) : _node(node) {} // 前置++:移动到下一个节点 __list_iterator& operator++() { _node = _node->_next; return *this; } // 后置++:返回当前迭代器后移动 __list_iterator operator++(int) { __list_iterator tmp = *this; // 拷贝当前状态 _node = _node->_next; return tmp; // 返回移动前的迭代器 } // 前置--:移动到前一个节点 __list_iterator& operator--() { _node = _node->_prev; return *this; } // 后置--:返回当前迭代器后移动 __list_iterator operator--(int) { __list_iterator tmp = *this; _node = _node->_prev; return tmp; } // 解引用:返回节点数据的引用 T& operator*() { return _node->_data; } // 箭头操作符:返回节点数据的指针 T* operator->() { return &_node->_data; } // 比较操作符:检查迭代器是否相等 bool operator==(const __list_iterator& other) const { return _node == other._node; } bool operator!=(const __list_iterator& other) const { return _node != other._node; } }; ``` - **作用**:实现类似标准迭代器的行为,包括`++`、`--`、`*`和`->`等操作。 - **细节**:后置`++`和`--`通过拷贝构造保留原状态,确保符合STL规范[^3][^4]。 #### 3. **list类(list)** list类管理整个链表,包括哨兵节点、大小维护和基本操作(如插入、删除)。使用哨兵节点(头节点)简化逻辑: ```cpp template<class T> class list { public: typedef __list_iterator<T> iterator; // 定义迭代器类型 // 构造函数:初始化哨兵节点(自环) list() { _head = new ListNode<T>(); // 创建哨兵节点 _head->_next = _head; // 初始化为自环 _head->_prev = _head; _size = 0; // 大小初始为0 } // 析构函数:释放所有节点 ~list() { clear(); // 清空链表 delete _head; // 删除哨兵节点 } // 迭代器接口 iterator begin() { return iterator(_head->_next); // 首元素是哨兵的下一个 } iterator end() { return iterator(_head); // 尾后位置是哨兵自身 } // 插入元素到指定位置前 iterator insert(iterator pos, const T& value) { ListNode<T>* newNode = new ListNode<T>(value); // 创建新节点 ListNode<T>* cur = pos._node; // 当前位置节点 ListNode<T>* prev = cur->_prev; // 前驱节点 // 链接新节点 prev->_next = newNode; newNode->_prev = prev; newNode->_next = cur; cur->_prev = newNode; _size++; // 更新大小 return iterator(newNode); // 返回新节点的迭代器 } // 删除指定位置元素 iterator erase(iterator pos) { if (pos == end()) return pos; // 不能删除哨兵 ListNode<T>* cur = pos._node; ListNode<T>* prev = cur->_prev; ListNode<T>* next = cur->_next; // 绕过当前节点 prev->_next = next; next->_prev = prev; delete cur; // 释放节点 _size--; // 更新大小 return iterator(next); // 返回下一个位置的迭代器 } // 添加元素到尾部 void push_back(const T& value) { insert(end(), value); } // 添加元素到头部 void push_front(const T& value) { insert(begin(), value); } // 清空链表 void clear() { iterator it = begin(); while (it != end()) { it = erase(it); // 逐个删除 } } // 获取链表大小 size_t size() const { return _size; } private: ListNode<T>* _head; // 哨兵节点(不存储数据) size_t _size; // 链表大小 }; ``` - **作用**:提供链表的核心功能,包括构造、析构、插入、删除和遍历。 - **细节**: - 哨兵节点`_head`形成自环,`begin()`指向第一个数据节点,`end()`指向哨兵,简化边界处理。 - `insert`和`erase`操作时间复杂度为$O(1)$,符合链表特性。 - `clear`和析构函数确保无内存泄漏[^1]。 #### 4. **测试示例** 简单测试代码: ```cpp #include <iostream> int main() { list<int> myList; myList.push_back(10); myList.push_front(20); auto it = myList.begin(); std::cout << *it << std::endl; // 输出20 it = myList.erase(it); std::cout << *it << std::endl; // 输出10 return 0; } ``` #### 总结 模拟实现C++ list的关键是: - **节点结构体**:管理数据和指针。 - **迭代器类**:封装遍历逻辑,通过运算符重载提供STL兼容接口。 - **list类**:使用哨兵节点简化操作,实现高效插入、删除和大小维护。 这种实现帮助深入理解链表底层机制,但实际开发中推荐使用标准库`std::list`以获得优化和安全性[^1][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值