模拟实现list

83 阅读3分钟

1、概念:带头双向循环链表

image-20240321140754206

定义链表

template <class T>
class list
{
    typedef ListNode<T> Node;
public:
    typedef listIterator<T, T&, T*> iterator;
    typedef listIterator<T, const T&, const T*> const_iterator;
public:
	Node* _head;
}

函数声明

//容量相关
bool empty() const;

// 增删查
void push_back(const T& val);
void pop_back();
void push_front(const T& val);
void pop_front();

// 获取首尾元素
T& front();
const T& front() const;
T& back();
const T& back() const;

// 迭代器
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;

函数实现

构造函数

list()
{
    _head = new Node;
    _head->_next = _head;
    _head->_prev = _head;
}

析构函数

~list()
{
    // 链表中的数据还没清理,这样会导致内存泄漏
    /*delete _head;
    _head = nullptr;*/
    clear();
    delete _head;
    _head = nullptr;
}

清空链表

void  clear()
{
    iterator it = begin();
    while (it != end())
    {
        it = erase(it);
    }
}

插入删除

void push_back(const T& val)
{
    // _head  tail  newnode
    Node* tail = _head->_prev;
    Node* newnode = new Node(val);
    tail->_next = newnode;
    newnode->_prev = tail;
    _head->_prev = newnode;
    newnode->_next = _head;
}

void pop_back()
{
    // _head prev tail
    Node* tail = _head->_prev;
    Node* prev = tail->_prev;
    prev->_next = _head;
    _head->_prev = prev;
}

void push_front(const T& val)
{
    // _head newnode next
    Node* next = _head->_next;
    Node* newnode = new Node(val);
    _head->_next = newnode;
    newnode->_prev = _head;
    newnode->_next = next;
    next->_prev = newnode;
}

void pop_front()
{
    // _head first second
    Node* first = _head->_next;
    _head->_next = first->_next;
    first->_prev = _head;
}

image-20240321140912776

image-20240321142459294

获取首尾元素

// 可读可写
T& front()
{
    return _head->_next->_val;
}

// 只读
const T& front() const
{
    return _head->_next->_val;
}

// 可读可写
T& back()
{
    return _head->_prev->_val;
}

// 只读
const T& back() const
{
    return _head->_prev->_val;
}

image-20240321142834337

迭代器

链表这里的迭代器不和stringvector的迭代器一样,stringvector是连续的物理空间,迭代器就是指针,对迭代器的++--操作都是符合指针的运算。链表这里就不能像原生指针这样计算,因为链表的物理空间是不连续的。

所以链表的迭代器要自定义类型。

template <class T>
struct listIterator
{
    typedef ListNode<T> Node;

    Node* _node;

    listIterator(Node* node)
        :_node(node)
    {
        // 用来调试打断点的
        int x = 10;
    }

    T& operator*()
    {
        return _node->_val;
    }

    T* operator->()
    {
        return &_node->_val;
    }

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

    // it++
    listIterator operator++(int)
    {
        listIterator tmp(*this);
        _node = _node->_next;
        return tmp;
    }

    // --it
    listIterator& operator--()
    {
        _node = _node->_prev;
        return *this;
    }

    // it--
    listIterator operator--(int)
    {
        listIterator tmp(*this);
        _node = _node->_prev;
        return tmp;
    }

    bool operator!=(listIterator it)
    {
        return _node != it._node;
    }
};

image-20240321161419684

如何定义const迭代器呢?

const迭代器的成员函数和普通迭代器一样,只是返回值有差异。

一种方法就是定义一个自定义的const_iterator类型,结果就是代码很冗余,可读性差。

另一种方式就是使用模板来解决这个问题。

template <class T, class Ref, class Ptr>
struct listIterator
{
    typedef ListNode<T> Node;

    Node* _node;

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

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

    Ptr operator->()
    {
        return &_node->_val;
    }

    // ++it
    listIterator<T,Ref,Ptr>& operator++()
    {
        _node = _node->_next;
        return *this;
    }

    // it++
    listIterator<T, Ref, Ptr> operator++(int)
    {
        listIterator tmp(*this);
        _node = _node->_next;
        return tmp;
    }

    // --it
    listIterator<T, Ref, Ptr>& operator--()
    {
        _node = _node->_prev;
        return *this;
    }

    // it--
    listIterator<T, Ref, Ptr> operator--(int)
    {
        listIterator tmp(*this);
        _node = _node->_prev;
        return tmp;
    }

    bool operator!=(listIterator it)
    {
        return _node != it._node;
    }
};

image-20240321170201610

任意位置插入删除

iterator insert(iterator pos, const T& val)
{
    // prev newnode cur
    Node* cur = pos._node;
    Node* prev = cur->_prev;

    Node* newnode = new Node(val);
    prev->_next = newnode;
    newnode->_prev = prev;
    newnode->_next = cur;
    cur->_prev = newnode;

    return pos;
}

iterator erase(iterator pos)
{
    Node* cur = pos._node;
    Node* prev = cur->_prev;
    Node* next = cur->_next;

    // prev cur next
    prev->_next = next;
    next->_prev = prev;

    delete cur;
    // 这样导致迭代器失效了
    //return pos;

    // 返回下一个位置的迭代器
    return iterator(next);
}

标准库中erase后是返回下一个位置的迭代器:

image-20240321171443928

标准库中insert后是返回新插入元素的迭代器:

image-20240321171549347