C++:STL——List的模拟实现


1. List的介绍和使用

  • list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
  • list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
  • list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。
  • 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。
  • 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)

更为详细的可以查看list文档介绍

list其他一些比较常用的接口

  • assign:将新内容分配到‎‎ list 中,替换其当前内容,并相应地修改其大小。(相当于是复制)
  • merge:将x合并到列表中,将其所有的元素在各自的有序位置转移到list中(两个list都应该是有序的,并且该操作相当于剪切)。
  • unique:从list中每一组连续的相等元素中删除除第一个元素以外的所有元素。注意,只有当一个元素与紧随其后的元素比较相等时,才会从list中移除。因此,这个函数对排序的列表特别有用。
  • sort:对list中的元素进行排序,改变它们在list中的位置。
  • reverse:反转list中元素的顺序。
  • remove:从list中移除所有等于val的元素。这将调用这些对象的析构器,并通过移除的元素数量减少容器的大小。
  • resize:调整list的大小,使其包含n个元素。如果n小于当前list的大小,内容就被缩减到最初的n个元素,删除那些超出的元素(并销毁它们)。如果n大于当前list的大小,内容将被扩展,在最后插入尽可能多的元素以达到n的大小。

2. List的模拟实现

代码如下:

#include <iostream>
#include <cstdlib>

using namespace std;


namespace myTest
{
    template <class _Ty>
        class List{
            protected:
                typedef size_t _Size;
                struct _Node;
                typedef _Node* _Nodeptr;
                struct _Node
                {
                    _Nodeptr _Next,_Prev;
                    _Ty value;
                };
                struct _ACC
                {
                    typedef _Node*& _Nodepref;
                    typedef _Ty& _Vref; 
                    static _Nodepref _Next(_Nodeptr _S)
                    {
                        return _S->_Next;
                    }
                    static _Nodepref _Prev(_Nodeptr _S)
                    {
                        return _S->_Prev;
                    }
                    static _Vref _Value(_Nodeptr _S)
                    {
                        return _S->value;
                    }
                };

                _Nodeptr  _BuyListNode(_Nodeptr Narg = 0,_Nodeptr Parg = 0)
                {
                    _Nodeptr _S = (_Nodeptr) malloc(sizeof(_Node));
                    _ACC::_Next(_S) = Narg != 0 ? Narg : _S;
                    _ACC::_Prev(_S) = Parg != 0 ? Parg : _S;
                    return _S;
                }

                void _FreeNode(_Nodeptr _S)
                {
                    free(_S);
                }

            public:
                class iterator
                {
                    public:
                        iterator()
                        {
                            cout << "Over create iterator!" << endl;
                        }
                        iterator(_Nodeptr ptr) : _Ptr(ptr)
                    {}
                        iterator(const iterator &_it)
                        {
                            this->_Ptr = _it._Ptr;
                        }

                        bool operator!=(iterator& _it) const
                        {
                            return _Ptr != _it._Ptr;
                        }
                        bool operator==(iterator& _it) const
                        {
                            return!(*this!=_it);
                        }
                        iterator& operator++()
                        {
                            _Ptr = _ACC::_Next(_Ptr);
                            return *this;
                        }
                        iterator operator++(int)
                        {
                            iterator tmp(*this);
                            ++(*this);
                            return tmp;
                        }
                        _Ty operator*()
                        {
                            return _ACC::_Value(_Ptr);
                        }
                        iterator& operator--()
                        {
                            _Ptr = _ACC::_Prev(_Ptr);
                            return *this;
                        }
                        iterator operator--(int)
                        {
                            iterator tmp(*this);
                            --(*this);
                            return tmp;
                        }
                        _Nodeptr _MyNode()
                        {
                            return _Ptr;
                        }

                    private:
                        _Nodeptr _Ptr;
                };

            public:
                explicit List():Head(_BuyListNode()),_size(0)
            {
                _ACC::_Next(Head) = Head;
                _ACC::_Prev(Head) = Head;
                cout << "Over create List<class _Ty>" << endl;
            } 
                List(_Size _n,const _Ty& _V = _Ty() ):Head(_BuyListNode()),_size(0)
            {
                insert(begin(),_n,_V);
            }
                List(const _Ty* _f,const _Ty* _l):Head(_BuyListNode()),_size(0)
            {
                insert(begin(),_f,_l);
            }
                ~List()
                {
                    clear();
                    _FreeNode(Head);
                    Head=0,_size=0;
                }
            public:
                _Size size() const
                {
                    return _size;
                }
                bool empty()const
                {
                    return _size==0;
                }
                _Ty& front()
                {
                    return *begin();
                }
                const _Ty& front() const
                {
                    return *begin();
                }
                _Ty& back()
                {
                    return *(--end());
                }

                void push_back(const _Ty& _val)
                {
                    insert(end(),_val);
                }
                void push_front(const _Ty& _val)
                {
                    insert(begin(),_val);
                }
                /*
                   void push_back(_Ty val)
                   {
                   _Nodeptr _tmp = _BuyListNode(Head,Head->_Prev); 
                   _ACC::_Value(_tmp) = val;
                   _ACC::_Prev(_ACC::_Next(_tmp)) = _tmp;
                   _ACC::_Next(_ACC::_Prev(_tmp)) = _tmp;

                   size++;
                   cout << "push_back access" << endl;
                   }
                   */

                iterator begin()const
                {
                    return iterator(_ACC::_Next(Head));
                }
                iterator end() const
                {
                    return iterator(Head);
                }
                iterator insert(iterator _it,_Ty val= _Ty())
                {
                    _Nodeptr _S = _it._MyNode();
                    _ACC::_Prev(_S) = _BuyListNode(_S,_ACC::_Prev(_S));
                    _S = _ACC::_Prev(_S);

                    _ACC::_Value(_S) = val;
                    _ACC::_Next(_ACC::_Prev(_S)) = _S;
                    ++_size;
                    cout << "iterator insert success!" << endl;
                    return iterator(_S);
                }
                iterator erase(iterator _it)
                {
                    _Nodeptr _S = (_it++)._MyNode();
                    _ACC::_Next(_ACC::_Prev(_S)) = _ACC::_Next(_S);
                    _ACC::_Prev(_ACC::_Next(_S)) = _ACC::_Prev(_S);

                    --_size;
                    _FreeNode(_S);
                    return _it;
                }

                void insert(iterator _it,_Size _M,const _Ty& _x)
                {
                    for(;0 < _M; --_M)
                        insert(_it,_x);
                }
                void insert(iterator _it,const _Ty*  _f,const _Ty* _l)
                {
                    while(_f!=_l)
                    {
                        insert(_it,*_f++);
                    }
                }
                iterator erase(iterator _itbegin, iterator _itend)
                {
                    while(_itbegin != _itend)
                    {
                        erase(_itbegin++);
                    }
                    return _itbegin;
                }
                void clear()
                {
                    erase(begin(),end());
                }




            private:        
                _Nodeptr Head;
                _Size _size;

        };
}

void test1()
{
    myTest::List<int> mylist;
    mylist.push_back(1);
    mylist.push_back(2);
}

void test2()
{
    myTest::List<int> mylist;
    mylist.push_back(1);
    mylist.push_back(2);
   	myTest::List<int>::iterator it1 = mylist.begin();
    myTest::List<int>::iterator it2 = mylist.end();

    while(it1 != it2)
    {
        cout << *it1 << "->";
        ++it1;
    }

    cout << "over print to iterator!" << endl;
}

void test3()
{
    int ar[] = {1,2,3,4,5,6,7,8,9,10};
    myTest::List<int> mylist(ar, ar+10);

    //mylist.erase(mylist.begin(), mylist.end()); //[  )
//    mylist.clear();

    myTest::List<int>::iterator it = mylist.begin();
    myTest::List<int>::iterator it1 = mylist.end();
    while(it != it1)
    {
        cout<<*it<<"-->";
        ++it; //it++
    }
    cout<<"Over."<<endl;
}


int main()
{
    //test1();
    //test2();
    test3();

    return 0;
}

3. List实现的不成文规定

  • 若定义的成员变量,只供自己内部使用,则需要加上下划线,例如:_Nodeptr Head;
  • 双向循环链表的最后一个节点是头节点。
  • 插入时,是在迭代器的前面进行插入。
  • end迭代器永远指向最后一个元素的下一个位置。
  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值