C++ 学习系列 -- std::list

一  std::list 介绍

       list 是 c++ 中的序列式容器,其实现是双向链表,每个元素都有两个指针,分别指向前一个节点与后一个节点

      链表与数组都是计算机常用的内存数据结构,与数组连续内存空间不一样的地方在于,链表的空间是不连续的,链表是将一块块不连续的内存串联起来使用。

    正是由于链表的内存不连续这一特点,所以不能像数组一样,可以根据位置随机的访问每个元素,而链表我们压根不知道每个元素的实际位置到底在哪块内存区域。

     查找某个元素需要遍历整个链表,直到找到目标元素位置,时间复杂度是 O(n);

    在链表中插入一个元素与删除一个元素的时间复杂度是 O(1);

二   c++ 中 stl 链表结构

1. list 结构

   list  结构 (借用侯捷老师的一张图片来):

  C++ 学习系列 -- std::list_第1张图片

  由上面的结构上可以看出,list 是一个循环链表,链表的尾端是一个空节点,不存储任何数据。

三   c++ 中 stl 链表使用

 1  构造函数

构造函数 说明
list() 空构造函数
list( size_type count, const T& value) 初始化一个元素数量为 count 个的 value 元素
list( std::initializer_list init) 利用列表初始化 list
list( InputIt first, InputIt last) 利用迭代器的起始于终止位置初始化 list

 2   容器修改

函数 说明
clear()  清空所有元素
insert 在指定位置插入元素
emplace 在指定位置插入元素, 可以通过直接传入元素类的构造参数实现原地构造
erase 移除指定元素
push_back append 元素到链表的尾部
pop_back 将链表尾部元素弹出
push_front append 元素到链表的头部
pop_front 将链表头部元素弹出
emplace_back append 元素到链表的尾部, 可以通过直接传入元素类的构造参数实现原地构造
emplace_front append 元素到链表的头部, 可以通过直接传入元素类的构造参数实现原地构造

 3  容器访问

函数 说明
begin 返回头部元素的迭代器
end 返回尾部元素的迭代器
rbegin 返回尾部元素的迭代器
rend 返回头部元素的迭代器
front 返回头部元素的引用
back 返回尾部元素的引用

4  容器容量

函数 说明
empty 判断 list是否为空
size 返回 list 存储元素的个数
#include
#include

int main()
{
     // 1. 构造函数
    std::list list;
    auto iter = list.begin();
    std::cout << *iter << "--- " << std::endl;;

    // 2. 容器修改
    list.push_back(1);
    list.push_back(2);
    list.push_back(3);
    list.push_back(4);
    list.push_back(5);
    list.push_front(11);
    list.push_front(22);

    list.pop_back();
    list.pop_front();

    list.insert(list.begin(), 666);

    // 3. 容器访问
    for(auto iter = list.begin(); iter != list.end();iter++)
    {
        std::cout << *iter << " "; // 666 11 1 2 3 4
    }
    std::cout << "" << std::endl;

    for(auto iter = list.rbegin(); iter != list.rend();iter++)
    {
        std::cout << *iter << " "; // 4 3 2 1 11 666
    }
    std::cout << "" << std::endl;
    std::cout << "first: " << list.front() << ", finish: " << list.back() << std::endl; // first: 666, finish: 4

    // 4. 容器容量
    std::cout << "empyt: " << list.empty() << std::endl; // 0
    std::cout << "size: "<< list.size() << std::endl; // 6

    list.clear();

    std::cout << "empyt: " << list.empty() << std::endl; // 1
    std::cout << "size: "<< list.size() << std::endl; // 0
    return 0;
}

四  简单实现

  

// my_list.h

#include
#include

template
struct _List_Node
{
    typedef _List_Node node;

    _List_Node()
    {
        prev = nullptr;
        next = nullptr;
    }

    _List_Node(T& da):data(da)
    {
        prev = nullptr;
        next = nullptr;
    }

    _List_Node(T&& da):data(da)
    {
        prev = nullptr;
        next = nullptr;
    }

    ~_List_Node()
    {
        prev = nullptr;
        next = nullptr;
    }

    node* prev;
    node* next;
    T data;
};

template
struct _List_Iterator
{
    typedef T valueType;
    typedef T& refrence;
    typedef T* pointer;

    typedef  _List_Node node;


    _List_Iterator(node* val):data(val)
    {

    }

    _List_Iterator& operator++()
    {
        this->data = this->data->next;
        return *this;
    }

    _List_Iterator operator++(int)
    {
        _List_Iterator tmp = *this;
        ++(*this);
        return tmp;
    }

    _List_Iterator& operator--()
    {
        this->data = this->data->prev;
        return *this;
    }

    _List_Iterator operator--(int)
    {
        _List_Iterator tmp = *this;
        --(*this);
        return tmp;
    }

    T& operator*()
    {
        return this->data->data;
    }

    bool operator != (_List_Iterator& other)
    {
        return this->data != other->data;
    }

    bool operator == (_List_Iterator& other)
    {
        return this->data == other.data;
    }

    bool operator != (_List_Iterator&& other)
    {
        return this->data != other.data;
    }

    bool operator == (_List_Iterator&& other)
    {
        return this->data == other.data;
    }

    node*  data;
};

template
class my_list
{
    typedef  _List_Node  node;
    typedef  _List_Iterator iterator;
public:
    my_list():count(0)
    {
        next_curr = new node;
        pre_curr = next_curr;

        finish = new node;
        next_curr->next = finish;
        finish->next = next_curr;

        pre_curr->prev = finish;
        finish->prev = pre_curr;
    }

    ~my_list()
    {
        node* tmp = pre_curr;
        while (tmp != nullptr) {
            node* tt = tmp->next;
            delete tmp;
            tmp = tt;
        }
    }

    void push_back(T& val)
    {
        std::cout << "count: " << count << std::endl;

        if(count == 0)
            next_curr->data = val;
        else {
            node* tmp = new node(val);
            tmp->next = next_curr->next;
            tmp->next->prev = tmp;
            next_curr->next = tmp;
            tmp->prev = next_curr;
            next_curr = next_curr->next;
        }
        count++;
    }

    void push_back(T&& val)
    {
        push_back(val);
    }

    void push_front(T& val)
    {
        if(count == 0)
            pre_curr->data = val;
        else {
            node* tmp = new node(val);
            tmp->prev = pre_curr->prev;
            pre_curr->prev->next = tmp;
            tmp->next = pre_curr;
            pre_curr->prev = tmp;

            pre_curr = pre_curr->prev;
        }
        count++;
    }

    void push_front(T&& val)
    {
        push_front(val);
    }

    void pop_back()
    {
        if(count == 0)
        {
            return;
        } else
        {
            node* tmp = next_curr;
            next_curr->prev->next = next_curr->next;
            next_curr->next->prev = next_curr->prev;
            next_curr = next_curr->prev;

            delete tmp;
            count--;
        }
    }

    void pop_front()
    {
        if(count == 0)
        {
            return;
        } else
        {
            node* tmp = pre_curr;
            finish->next = pre_curr->next;
            pre_curr->next->prev = finish;
            pre_curr = pre_curr->next;
            delete tmp;
            count--;
        }
    }

    int size()
    {
        return count;
    }

    iterator begin()
    {
        return iterator(pre_curr);
    }

    iterator end()
    {
        return iterator(finish);
    }

    iterator rbegin()
    {
        return iterator(finish->prev);
    }

    iterator rend()
    {
        return iterator(pre_curr->prev);
    }

    void insert(iterator pos, T& val)
    {
        node* tmp = new node(val);

        pos.data->prev->next = tmp;
        tmp->prev = pos.data->prev;
        tmp->next = pos.data;
        pos.data->prev = tmp;
        if(pos.data == pre_curr)
        {
            pre_curr = pre_curr->prev;
        }
        else if(pos.data == next_curr){
            next_curr = next_curr->next;
        }
        count++;
    }

    void insert(iterator pos, T&& val)
    {
        insert(pos, val);
    }

    template
    void emplace(iterator pos, Args... args)
    {
        node* tmp = new node(std::forward(args)...);
        pos.data->prev->next = tmp;
        tmp->prev = pos.data->prev->next;
        tmp->next = pos.data;
        pos.data->prev = tmp;
        count++;
    }

    void erase(iterator pos)
    {
        node* tmp = pos.data;
        tmp->prev = tmp->next;
        delete tmp;
        count--;
    }

    void clear()
    {
        while (pre_curr->next != finish) {
            pop_back();
        }
        count = 0;
    }

    T& front()
    {
        return pre_curr->data;
    }

    T& back()
    {
        return next_curr->data;
    }

    bool empty()
    {
        return count == 0;
    }

public:
    node* next_curr = nullptr;
    node* pre_curr = nullptr;
    node* finish = nullptr;
    int count;
};

// main.cpp
#include
#include

int main()
{
     // 1. 构造函数
    my_list list;

    // 2. 容器修改
    list.push_back(1);
    list.push_back(2);
    list.push_back(3);
    list.push_back(4);
    list.push_back(5);
    list.push_front(11);
    list.push_front(22);

    // 22 11 1 2 3 4 5
    list.pop_back();
    list.pop_front();
    list.insert(list.begin(), 666);


    // 3. 容器访问
    for(auto iter = list.begin(); iter != list.end();iter++)
    {
        std::cout << *iter << " "; // 666 11 1 2 3 4
    }
    std::cout << "" << std::endl;

    for(auto iter = list.rbegin(); iter != list.rend();iter--)
    {
        std::cout << *iter << " "; // 4 3 2 1 11 666
    }
    std::cout << "" << std::endl;
    std::cout << "first: " << list.front() << ", finish: " << list.back() << std::endl; // first: 666, finish: 4

    // 3. 容器容量
    std::cout << "empty: " << list.empty() << std::endl; // 0
    std::cout << "size: "<< list.size() << std::endl; // 6

    list.clear();

    std::cout << "empyt: " << list.empty() << std::endl; // 1
    std::cout << "size: "<< list.size() << std::endl; // 0

    return 0;
}

你可能感兴趣的:(c++,学习,开发语言)