STL库中的list的使用和模拟实现

简单介绍list

上文我们讲到了STL库中的vector的使用和模拟实现,其实list和vector在很多地方都有相似之处。STL库中的list是一个双向循环链表。它的简单的结构如图
这里写图片描述

我们还是先来看看它里面有什么。

list的内容与使用

一.
这里写图片描述
首先还是雷打不动的三个成员函数,构造函数,析构函数和赋值运算符重载。

二.
这里写图片描述
其次是迭代器。这里需要注意一下的是,begin()返回的是第一个元素的位置,也就是头节点head的下一个位置;end()返回的是最后一个元素的下一个位置,也就是头节点head的位置。在这里我们讲一下迭代器失效的问题。

int main()
{
    int a[] = { 1,2,3,4 };
    list<int> mylist(a,a+4);
    list<int>::iterator it = mylist.begin();
    while (it != mylist.end())
    {
        if (*it % 2 == 0)
        {
            mylist.erase(it);
        }
        else
        {
            ++it;   
        }
    }
    return 0;
}

上面的代码程序会崩溃,因为在STL里,我们不能以指针来看待迭代器,指针是与内存绑定的,而迭代器是与容器里的元素绑定的,删除了之后,该迭代器就失效了,在对其重新赋值之前,不能再访问此迭代器。

int main()
{
    int a[] = { 1,2,3,4 };
    list<int> mylist(a,a+4);
    list<int>::iterator it = mylist.begin();
    while (it != mylist.end())
    {
        if (*it % 2 == 0)
        {
            it= mylist.erase(it);
        }
        else
        {
            ++it;
        }
    }
}

这样就不会崩溃了,用it重新接收一下erase的返回值,因为erase的返回值是删除节点的下一个节点。
rbegin()与rend()是逆序访问链表的意思,和vector的用法差不多。

三.
这里写图片描述
上面的用法与vector的也差不多,就不一一介绍了。

四.
这里写图片描述
front():返回第一个节点的数据;
back():返回最后一个节点的数据;

五.
这里写图片描述
这些操作中,只比vector多了两个操作函数。
push_front():头插。
pop_front():头删。
这两个函数非常的简单,就不举例一一测试了。
insert函数有两种参数的用法;

int main()
{
    int a[] = { 1,2,3,4 };
    list<int> mylist(a,a+4);
    mylist.insert(mylist.begin(), 0);//在首元素的前面插入一个0
    mylist.insert(mylist.end(), 3, 5);//在尾元素的后面插入三个5
    list<int>::iterator it;
    for (it = mylist.begin(); it != mylist.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;
    system("pause");
    return 0;
}

这里写图片描述

六.

这里写图片描述
这是list中容器适配器的内容,我们来仔细看一下。

splice():往一个list1的某一个位置插入list2的内容。

int main()
{
    list<int> mylist1, mylist2;
    for (size_t i = 1; i <= 3; ++i)
    {
        mylist1.push_back(i);  //mylist1: 1 2 3
        mylist2.push_back(i * 10);// mylist2: 10 20 30
    }
    list<int>::iterator it;
    it = mylist1.begin();
    ++it;//"it" points 2 now
    mylist1.splice(it, mylist2);//mylist1: 1 10 20 30 2 3
                                //mylist2(empty)
                                //"it" still points to 2
    mylist2.splice(mylist2.begin(), mylist1, it);//mylist1: 1 10 20 30 3
                                                 //mylist2: 2
                                                 //"it" now is invalid
    it = mylist1.begin();
    advance(it, 3);//"it" points to 30
    mylist1.splice(mylist1.begin(), mylist1, it, mylist1.end());
                                                 //mylist1: 30 3 1 10 20
    for (it = mylist1.begin(); it != mylist1.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;
    for (it = mylist2.begin(); it != mylist2.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;
    system("pause");
    return 0;
}

remove():找出value然后删除;

int main()
{
    int a[] = { 1, 2, 3, 4 };
    list<int> mylist(a,a+4);
    list<int>::iterator it;
    mylist.remove(1);
    for (it = mylist.begin(); it != mylist.end(); ++it)
    {
        cout << *it << " ";
    }   
    cout << endl;
    system("pause");
    return 0;
}

这里写图片描述

remove_if():条件删除,把不符合条件的删除;

bool check(const int& value)//判断是否小于4
{
    return(value < 4);
}

int main()
{
    int a[] = { 1, 2, 3, 4 };
    list<int> mylist(a,a+4);
    list<int>::iterator it;
    mylist.remove_if(check);
    for (it = mylist.begin(); it != mylist.end(); ++it)
    {
        cout << *it << " ";
    }   
    cout << endl;
    system("pause");
    return 0;
}

这里写图片描述

unique():去掉重复的数值(需要注意的是,unique是有序的条件下去重,使用之前最好先排序)

int main()
{
    int a[] = { 1, 2, 4, 4 };
    list<int> mylist(a,a+4);
    list<int>::iterator it;
    mylist.unique();
    for (it = mylist.begin(); it != mylist.end(); ++it)
    {
        cout << *it << " ";
    }   
    cout << endl;
    system("pause");
    return 0;
}

这里写图片描述

sort():排序

int main()
{
    int a[] = { 1, 4 ,2, 3 };
    list<int> mylist(a,a+4);
    list<int>::iterator it;
    mylist.sort();
    for (it = mylist.begin(); it != mylist.end(); ++it)
    {
        cout << *it << " ";
    }   
    cout << endl;
    system("pause");
    return 0;
}

这里写图片描述

reverse():逆序

int main()
{
    int a[] = { 1, 4 ,2, 3 };
    list<int> mylist(a,a+4);
    list<int>::iterator it;
    mylist.reverse();
    for (it = mylist.begin(); it != mylist.end(); ++it)
    {
        cout << *it << " ";
    }   
    cout << endl;
    system("pause");
    return 0;
}

这里写图片描述

merge():合并有序的链表。

int main()
{
    int a[] = { 1, 2 ,3, 4 };
    int b[] = { 5, 6, 7, 8 ,9};
    list<int> mylist1(a,a+4);
    list<int> mylist2(b, b + 5);
    list<int>::iterator it;
    mylist1.merge(mylist2);
    for (it = mylist1.begin(); it != mylist1.end(); ++it)
    {
        cout << *it << " ";
    }   
    cout << endl;
    system("pause");
    return 0;
}

这里写图片描述

模拟实现list

#pramga once
#include <iostream>
using namespace std;

#include <assert.h>


//链表节点的结构
template <class T>
struct ListNode
{
    T _data;
    ListNode<T>* _prev;
    ListNode<T>* _next;

    ListNode(const T& data)//给一个const T类型的引用
        :_data(data)
        , _prev(NULL)
        , _next(NULL)
    {}
};


//链表的迭代器
template <class T,class Ptr,class Ref>
struct ListIterator
{
    typedef ListNode<T> Node;
    typedef ListIterator<T, T*, T&> Iterator;
    typedef ListIterator<T,Ptr,Ref> Self;

    Node* _node;

    ListIterator(Node* node)//给一个链表节点的指针
        :_node(node)
    {}

    ListIterator()
    {}

    ListIterator(const Self& it)
    {
        _node = it._node;
    }

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

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

    Self& operator++()//前置++
    {
        _node = _node->_next;
        return *this;
    }

    Self operator++(int)//后置++
    {
        Self tmp(*this);
        _node = _node->_next;
        return tmp;
    }

    Self& operator--()//前置--
    {
        _node = _node->_prev;
        return *this;
    }

    Self operator--(int)//后置--
    {
        Self tmp(*this);
        _node = _node->_prev;
        return tmp;
    }

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

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

//双向循环链表
template <class T>
class MyList
{
    typedef ListNode<T> Node;
public:
    typedef ListIterator<T, T*, T&> Iterator;
    MyList()
    {
        _head = BuyNode(T());
        _head->_next = _head;
        _head->_prev = _head;
    }

    ~MyList()
    {
        Clear();
        delete _head;
        _head = NULL;
    }

    //访问相关接口
    Iterator Begin() 
    {
        return _head->_next;
    }

    Iterator End() 
    {
        return _head;
    }

    T& Front()
    {
        return _head->_next->_data;
    }

    T& Back()
    {
        return _head->_prev->_data;
    }

    bool Empty()
    {
        return _head->_next == _head&&_head->_prev == _head;    
    }

    size_t Size()
    {
        size_t count = 0;
        Node* cur = _head->_next;
        while (cur != _head)
        {
            count++;
            cur = cur->_next;
        }
        return count;
    }

    //插入相关接口
    void PushBack(const T& x)
    {
        /*Node* newNode = BuyNode(x);
        Node* tail = _head->_prev;
        newNode->_next = _head;
        tail->_next = newNode;
        newNode->_prev = _head;
        _head->_prev = newNode;*/
        Insert(End(), x);
    }

    void PushFront(const T& x)
    {
        /*Node* newNode = BuyNode(x);
        Node* next = _head->_next;
        newNode->_next = next;
        next->_prev = newNode;
        newNode->_prev = _head;
        _head->_next = newNode;*/
        Insert(Begin(), x);
    }

    Iterator Insert(Iterator pos, const T& x)
        //在pos前面插入一个元素,返回新加入元素的迭代器
    {
        Node* newNode = BuyNode(x);
        Node* cur = pos._node;
        newNode->_next = cur;
        cur->_prev->_next = newNode;
        newNode->_prev = cur->_prev;
        cur->_prev = newNode;
        return Iterator(newNode);   
    }

    void Insert(Iterator pos, size_t n, const T& x)
        //在pos位置之前插入n个x元素,与上一个Insert形成重载
    {
        for (size_t i = 0; i < n; ++i)
        {
            Insert(pos, x);
        }
    }

    void Insert(Iterator pos, Iterator b, Iterator e)
        //在pos的位置插入[b,e)的内容
    {
        Iterator tmp = b;
        for (tmp = b; tmp != e; tmp++)
        {
            Insert(pos, tmp._node->_data);
        }
    }

    //删除相关接口
    Iterator Erase(Iterator pos)
    {
        assert(pos != End());
        Node* cur = pos._node;
        Node* del = cur;
        cur = cur->_next;
        del->_prev->_next = del->_next;
        del->_next->_prev = del->_prev;
        delete del;
        del = NULL;
        return Iterator(cur);
    }

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

    void PopFront()
    {
        Erase(Begin());
    }
    //打印相关接口
    void Print()
    {
        Node* cur = _head->_next;
        while (cur != _head)
        {
            cout << cur->_data << " ";
            cur = cur->_next;
        }
    }
protected:
    Node* BuyNode(const T& x)
    {
        Node* newNode = new Node(x);
        return newNode;
    }

    void Clear()
    {
        Node* cur = _head->_next;
        while (cur != _head)
        {
            Node* tmp= cur->_next;
            delete cur;
            cur = tmp;
        }
        _head->_next = _head;
        _head->_prev = _head;
    }
protected:
    Node* _head;
};

相关测试代码如下

void TestMyList1()//测试PushBack
{
    int a[] = { 1, 2, 3, 4 };
    MyList<int> list;
    for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
    {
        list.PushBack(a[i]);
    }
    list.Print();
    cout << endl;
}

这里写图片描述

void TestMyList2()//测试PushFront
{
    int a[] = { 1, 2, 3, 4 };
    MyList<int> list;
    for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
    {
        list.PushBack(a[i]);
    }
    list.PushFront(0);
    list.Print();
    cout << endl;
}

这里写图片描述

void TestMyList3()//测试Insert
{
    int a1[] = { 1, 2, 3, 4 };
    MyList<int> list1;
    for (size_t i = 0; i < sizeof(a1) / sizeof(a1[0]); ++i)
    {
        list1.PushBack(a1[i]);
    }
    MyList<int>::Iterator it=list1.Begin();
    //测试第一个insert
    it=list1.Insert(it, 0);
    list1.Print();
    cout << endl;

    //测试第二个insert
    it = list1.End();
    list1.Insert(it, 3, 5);
    list1.Print();
    cout << endl;

    //测试第三个insert
    it--;
    int a2[] = { 1, 2, 3, 4 };
    MyList<int> list2;
    for (size_t i = 0; i < sizeof(a2) / sizeof(a2[0]); ++i)
    {
        list2.PushBack(a2[i]);
    }
    list1.Insert(it, list2.Begin(), list2.End());
    list1.Print();
    cout << endl;
}

这里写图片描述

void TestMyList4()//测试PopBack、PopFront、Erase
{
    int a[] = { 1, 2, 3, 4 };
    MyList<int> list;
    for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
    {
        list.PushBack(a[i]);
    }
    list.PopBack();//删除4,剩1 2 3
    list.PopFront();//删除1,剩2 3
    list.Erase(list.Begin());//删除2
    list.Print();
    cout << endl;
}

这里写图片描述

void TestMyList5()//测试其他接口
{
    int a[] = { 1, 2, 3, 4 };
    MyList<int> list;
    for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
    {
        list.PushBack(a[i]);
    }
    int size = list.Size();
    cout << size;
    cout << endl;
    int num1 = list.Front();
    cout << num1;
    cout << endl;
    int num2 = list.Back();
    cout << num2;
    cout << endl;
    list.PopBack();
    list.PopBack();
    list.PopBack();
    cout << list.Empty();
    cout << endl;
}

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值