C++Helper--在原std::list基礎上改進接口:新增、刪除、查詢、遍歷、數據轉換、集成算法等

  同vector一樣,list也是常用的一種STL容器。

  list爲雙線列表,能夠快讀的插入和刪除元素,在實際項目中也是應用廣泛,但不支持隨機訪問,已有接口不夠豐富,或是缺少常用的接口,於是本文意在原list基礎上,改進或新增應用接口。

  本文源碼見【完整代碼】章節,或GitHub:https://github.com/deargo/cpphelper

list介紹

  list 也是順序容器的一種,它是一個雙向鏈表(doubly-linked list)。

  list將元素按順序存儲在鏈表中,表的每個元素中都有一個指針指向後一個元素,也有一個指針指向前一個元素,如下圖所示。

  當然,list的用法和vector很類似,也擁有順序容器中的常用方法,但需要注意的是,list不支持使用下標隨機存取元素。

  在 list 容器中,在已經定位到要增刪元素的位置的情況下,只需修改幾個指針而已,增刪元素能在常數時間內完成。如下圖所示,在 ai 和 ai+1 之間插入一個元素,只需要修改 ai 和 ai+1 中的指針即可:

  所以它和向量(vector)相比,能夠快速的插入和刪除,但是,隨機訪問卻比較慢。

接口改進

  list的許多函數,其用法都與 vector 類似,除了順序容器都有的成員函數外,還獨有push_front、pop_front、sort、remove、unique、merge、splice等接口,這給我們提供了遍歷,但部分接口不夠豐富,需要拓展。

  由於自身結構的問題,list不支持隨機訪問,所以不支持隨機訪問迭代器,不支持下標操作符 [ ]、at等隨機訪問接口。雖然隨機訪問不夠效率,代價大,但還是不免使用到這種場景,需要新增。

完整代碼

  本文源碼見【完整代碼】章節,或GitHub:https://github.com/deargo/cpphelper

#pragma once

#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif

#include <list>
#include <set>
#include <vector>
#include <algorithm>
#include <functional>
#include <assert.h>

namespace CppHelper
{
template<class Type , class Alloc = std::allocator<Type> >
class CList : public std::list<Type,Alloc>{
    using StdList = std::list<Type,Alloc>;

public:
    explicit CList(const Alloc& alloc = Alloc()):StdList(alloc) {}                                          //默認構造函數
    explicit CList(typename CList::size_type n, const Type& val = Type(), const Alloc& alloc = Alloc()):StdList(n,val,alloc){} //容量構造函數
    CList(CList&& other):StdList(std::forward<CList>(other)){ }                                             //拷貝構造函數
    CList(const std::list<Type,Alloc>& vec){ StdList::assign(vec.begin(), vec.end()); }                     //可用std::list初始化
    template <class InitIterator>                                                                           //可用迭代器初始化
    CList (InitIterator first, InitIterator last, const Alloc& alloc = Alloc()):StdList(first,last,alloc){}
    explicit CList(const std::set<Type>& set){ StdList::assign(set.begin(), set.end()); }                   //可用std::set初始化
    explicit CList(const std::vector<Type>& vec){ StdList::assign(vec.begin(), vec.end()); }                //可用std::vector初始化

public:
    operator std::list<Type,Alloc>(){ return *this; }                                                  //類型轉換函數,可直接轉換爲std::list
    bool operator == (const CList& other) const{ return StdList::size()==other.size() && std::equal(StdList::begin(),StdList::end(),other.begin()); }
    bool operator !=(const CList& other) const { return StdList::size()!=other.size() || false == std::equal(StdList::begin(),StdList::end(),other.begin()); }
    Type& operator [](typename CList::size_type index){ assert(index<StdList::size()); typename CList::iterator it = CList::begin(); while(index--) ++it; return *it; }
    const Type& operator [](typename CList::size_type index) const { assert(index<StdList::size());typename CList::const_iterator it = CList::begin(); while(index--) ++it; return *it; }
    CList& operator =(const CList& other){StdList::assign(other.begin(), other.end()); return *this;}  //賦值構造函數
    CList& operator +(const CList& other){ push_back(other); return *this; }
    CList& operator +=(Type&& value){ push_back(std::forward<Type>(value)); return *this; }
    CList& operator +=(const CList& other){ push_back(other); return *this; }
    CList& operator<<(Type&& value){ push_back(std::forward<Type>(value)); return *this; }
    CList& operator<<(const CList& other){ push_back(other); return *this; }
    CList& operator<<(const std::set<Type>& set){ push_back(set); return *this; }
    CList& operator<<(const std::vector<Type>& vec){ push_back(vec); return *this; }

public:
    void append(Type&& value){ push_back(std::forward<Type>(value)); }
    void append(const CList& other){ push_back(other); }
    void append(const std::set<Type>& set){ push_back(set); }
    void append(const std::vector<Type>& vec){ push_back(vec); }

    const Type& at(typename CList::size_type index) const{ return this->operator[](index);  }

    bool contains(Type&& value) const
    {
        return  std::find(StdList::begin(), StdList::end(),std::forward<Type>(value)) != StdList::end();
    }
    template <class CompareFunction>  //需要傳入類似 bool (*compareFunction)(Type&& v1, Type&& v2) 的二元謂詞函數,v1爲element-value,v2爲input-value
    bool contains(Type&& value,CompareFunction compareFunction) const
    {
        return  std::find_if(StdList::begin(), StdList::end(),
                             std::bind(compareFunction,std::placeholders::_1,std::forward<Type>(value)))
                != StdList::end();
    }

    void copy(const CList& other){ CList::assign(other.begin(),other.end());}
    void copy(typename CList::size_type n, Type&& value) {StdList::assign(n,std::forward<Type>(value));}
    template <class CopyIterator>
    void copy(CopyIterator first,CopyIterator last) { CList::assign(first,last); }
    template <class CopyIterator, class Function>
    void copy(CopyIterator first,CopyIterator last, Function func)
    {
        StdList::clear();
        while (first!=last) {
            if(func(*first))
            {
                StdList::emplace_back(*first);
            }
            ++first;
        }
    }
    template <class CopyIterator>
    void copy(CopyIterator first, typename CList::size_type n)
    {
        StdList::clear();
        while (n) {
            StdList::emplace_back(*first);
            --n;
            ++first;
        }
    }

    typename CList::size_type count(Type&& value) const
    {
        return std::count(StdList::begin(), StdList::end(),std::forward<Type>(value));
    }
    template <class CompareFunction>  //需要傳入類似 bool (*compareFunction)(Type&& v1, Type&& v2) 的二元謂詞函數,v1爲element-value,v2爲input-value
    typename CList::size_type count(Type&& value,CompareFunction compareFunction) const
    {
        return  std::count_if(StdList::begin(), StdList::end(),
                              std::bind(compareFunction,std::placeholders::_1,std::forward<Type>(value)));
    }

    bool equal(const CList& other) const { return this->operator==(other); }
    template <class CompareIterator>
    bool equal(CompareIterator compareIterator) const
    {
        return std::equal(StdList::begin(),StdList::end(),compareIterator);
    }
    template <class CompareIterator, class CompareFunction> //需要傳入類似 bool (*compareFunction)(Type&& v1, Type&& v2) 的二元謂詞函數,v1爲element-value,v2爲input-value
    bool equal(CompareIterator compareIterator,CompareFunction compareFunction) const
    {
        return std::equal(StdList::begin(),StdList::end(),compareIterator,compareFunction);
    }

    void fill(Type&& value, typename CList::iterator first=StdList::begin(), typename CList::iterator last=StdList::end()) { std::fill(first,last,std::forward<Type>(value)); }
    void fill(typename CList::size_type n, Type&& value, typename CList::iterator first=StdList::begin())  { std::fill_n(first,n,std::forward<Type>(value)); }

    typename CList::iterator find(Type&& value)
    {
        return  std::find(StdList::begin(), StdList::end(),std::forward<Type>(value));
    }
    typename CList::const_iterator find(Type&& value) const
    {
        return  std::find(StdList::begin(), StdList::end(),std::forward<Type>(value));
    }
    template <class CompareFunction>  //需要傳入類似 bool (*compareFunction)(Type&& v1, Type&& v2) 的二元謂詞函數,v1爲element-value,v2爲input-value
    typename CList::iterator find(Type&& value,CompareFunction compareFunction)
    {
        return  std::find_if(StdList::begin(), StdList::end(),
                             std::bind(compareFunction,std::placeholders::_1,std::forward<Type>(value)));
    }
    template <class CompareFunction>  //需要傳入類似 bool (*compareFunction)(Type&& v1, Type&& v2) 的二元謂詞函數,v1爲element-value,v2爲input-value
    typename CList::const_iterator find(Type&& value,CompareFunction compareFunction ) const
    {
        return  std::find_if(StdList::begin(), StdList::end(),
                             std::bind(compareFunction,std::placeholders::_1,std::forward<Type>(value)));
    }

    const Type& first() const{ return *StdList::begin(); }

    template <class Function>
    Function for_each(Function func){ return std::for_each(StdList::begin(), StdList::end(),func); }

    int index(Type&& value) const {
        for (int idx = 0; idx <(int)StdList::size();++idx){
            if (this->operator[](idx)==std::forward<Type>(value)) return idx;
        }
        return -1;
    }
    template <class CompareFunction>  //需要傳入類似 bool (*compareFunction)(Type&& v1, Type&& v2) 的二元謂詞函數,v1爲element-value,v2爲input-value
    int index(Type&& value,CompareFunction compareFunction) const {
        for (int idx = 0; idx <(int)StdList::size();++idx){
            if (compareFunction(this->operator[](idx),std::forward<Type>(value))) return idx;
        }
        return -1;
    }

    void insert(typename CList::size_type index, Type&& value)
    {
        typename StdList::iterator it=StdList::begin();
        while (index --)  ++it;
        StdList::insert(it, std::forward<Type>(value));
    }

    const Type& last() const{ return this->operator[](StdList::size() - 1); }

    void prepend(Type&& value) { StdList::emplace(StdList::begin(), std::forward<Type>(value)); }

    void push_back(Type&& value){ StdList::emplace_back(std::forward<Type>(value)); }
    void push_back(const CList& other){  StdList::insert(StdList::end(),other.begin(),other.end());}
    void push_back(const std::set<Type>& set){ StdList::insert(StdList::end(),set.begin(),set.end()); }
    void push_back(const std::vector<Type>& vec){ StdList::insert(StdList::end(),vec.begin(),vec.end()); }

    void push_front(Type&& value) { StdList::emplace(StdList::begin(), std::forward<Type>(value)); }

    void remove(Type&& value) { StdList::remove(std::forward<Type>(value)); }
    template <class CompareFunction>  //需要傳入類似 bool (*compareFunction)(Type&& v1, Type&& v2) 的二元謂詞函數,v1爲element-value,v2爲input-value
    void remove(Type&& value, CompareFunction compareFunction)
    {
        StdList::remove_if(std::bind(compareFunction,std::placeholders::_1,std::forward<Type>(value)));
    }
    void removeAll(){ StdList::clear(); }
    void removeAt(unsigned int index)
    {
        typename StdList::iterator it=StdList::begin();
        while (index --)  ++it;
        StdList::erase(it);
    }
    void removeFirst(){ StdList::pop_front(); }
    void removeLast(){ StdList::pop_back(); }
    void removeRange(unsigned int from, unsigned int to)
    {
        typename StdList::iterator first=StdList::begin(),last=StdList::begin();
        while (from --)  ++first;
        while (to --)  ++last;
        StdList::erase(first,last);
    }
    void replace(unsigned int index, Type&& value){ this->operator[](index) = std::forward<Type>(value); }

    void swap (std::list<Type,Alloc>& other){ return StdList::swap(other);}
    void swap (unsigned int index1,unsigned int index2){ return std::swap(this->operator[](index1),this->operator[](index2));}

    const Type& takeAt(unsigned int index) const{ return this->operator[](index); }
    const Type& takeFirst() const { return *StdList::begin(); }
    const Type& takeLast() const { return this->operator[](StdList::size() - 1); }

    std::list<Type> toStdList() const { return *this; }
    std::vector<Type> toStdVec() const{ return std::vector<Type>(StdList::begin(),StdList::end());}
    std::set<Type> toStdSet() const{ return std::set<Type>(StdList::begin(),StdList::end());}

    const Type& value(unsigned int index) const { return this->operator[](index); }
};
}

測試代碼

    typedef std::set<int> StdSet;
    typedef std::list<int> StdList;
    typedef std::vector<int> StdVec;
    typedef CppHelper::CList<int> NewList;


#define TEST_list_bool(b) (b ? "true" : "false")
#define TEST_list_exec(flage,code) cout << "line["<< __LINE__ << "]: "<< flage << code << endl
#define TEST_list_show(flage,val) cout << "line["<< __LINE__ << "]: "<< flage ;\
    for(auto it = val.begin();it!=val.end();++it) cout << *it << " ";\
    if(val.empty()) cout << "empty";\
    cout << endl

    int arr[] = {1,2,3,4,5,6,7,8,9};
    StdSet stdSet{11,12,13,14,15,16,17,18,19};
    StdList stdList{21,22,23,24,25,26,27,28,29};
    StdVec stdVec1{31,32,33,34,35,36,37,38,39};

    NewList newList1;
    NewList newList2(10);
    NewList newList3(stdSet);
    NewList newList4(stdList);
    NewList newList5(stdVec1);
    NewList newList6(arr,arr+9);
    TEST_list_show(" stdSet: ",stdSet);
    TEST_list_show("stdList: ",stdList);
    TEST_list_show("stdVec1: ",stdVec1);
    TEST_list_show("newList1: ",newList1);
    TEST_list_show("newList2: ",newList2);
    TEST_list_show("newList3: ",newList3);
    TEST_list_show("newList4: ",newList4);
    TEST_list_show("newList5: ",newList5);
    TEST_list_show("newList6: ",newList6);

    TEST_list_exec("newList3 == newList4 ? : ",TEST_list_bool(newList3 == newList4));
    TEST_list_exec("newList3 != newList4 ? : ",TEST_list_bool(newList3 != newList4));

    newList1 = newList3;
    newList1 += newList4;
    newList1 << 100 << 200<< 300;
    TEST_list_show("newList1: ",newList1);

    TEST_list_exec("newList1.size()    : ",newList1.size());
    newList1.clear();
    TEST_list_exec("newList1.size()    : ",newList1.size());
    TEST_list_show("newList1: ",newList1);

    newList1.append(555);
    newList1.append(newList3);
    newList1.append(stdSet);
    newList1.append(stdList);
    TEST_list_show("newList1: ",newList1);

    TEST_list_exec("newList1.at(11) : ",newList1.at(11));

    newList1.contains(200,[](const int& v1,int v2){ return v1>v2;});
    TEST_list_exec("newList1.contains(555) : ",TEST_list_bool(newList1.contains(555)));
    TEST_list_exec("newList1.contains(>200): ",TEST_list_bool(newList1.contains(200,[](const int& v1,int v2){ return v1>v2;})));
    TEST_list_exec("newList1.count(11) : ",newList1.count(11));
    TEST_list_exec("newList1.count(>28): ",newList1.count(28,[](int v1, int v2){ return v1>v2;}));

    newList1.clear();
    newList1.resize(20);
    TEST_list_show("newList3      : ",newList3);
    TEST_list_show("newList1      : ",newList1);
    newList1.copy(newList3);
    TEST_list_show("newList1.copy1: ",newList1);
    newList1.copy(3,111);
    TEST_list_show("newList1.copy2: ",newList1);
    newList1.copy(newList3.begin(),newList3.end());
    TEST_list_show("newList1.copy3: ",newList1);
    newList1.copy(newList3.begin(),newList3.end(),[](int v){ return v>15; });
    TEST_list_show("newList1.copy4: ",newList1);
    newList1.copy(newList3.begin(),7);
    TEST_list_show("newList1.copy5: ",newList1);

    TEST_list_exec("newList1.count(15) : ",newList1.count(15));
    TEST_list_exec("newList1.count(>15): ",newList1.count(15,[](int v1,int v2){ return v1>v2; }));

    TEST_vec_show("newList1                  : ",newList1);
    TEST_vec_show("newList3                  : ",newList3);
    TEST_vec_exec("newList1.equal1(newList3) : ",TEST_vec_bool(newList1.equal(newList3)));
    TEST_vec_exec("newList1.equal2(newList3) : ",TEST_vec_bool(newList1.equal(newList3.begin())));
    TEST_vec_exec("newList1.equal3(newList3) : ",TEST_vec_bool(newList1.equal(newList3.begin(),[](int v1,int v2){ return v1==v2; })));

    newList1.clear();
    newList1.resize(5);
    TEST_list_show("newList1        : ",newList1);
    newList1.fill(111,newList1.begin(),newList1.end());
    TEST_list_show("newList1.fill-1 : ",newList1);
    newList1.resize(10);
    newList1.fill(5,222,newList1.begin());
    TEST_list_show("newList1.fill-2 : ",newList1);

    newList1.copy(newList3);
    TEST_list_show("newList1           : ",newList1);
    TEST_list_exec("newList2.find(13)  : ",*(newList1.find(13)));
    TEST_list_exec("newList2.find(<=13): ",*(newList1.find(13,[](int vecVal,int findVal){ return vecVal<=findVal;})));

    cout << "newList1.for_each: ";
    newList1.for_each([](int v){ cout << v << " "; });
    cout << endl;

    TEST_list_exec("newList1.index(15)            : ",newList1.index(15));
    TEST_list_exec("newList1.index(<100 && >=15)  : ",newList1.index(15,[](int vecVal,int findVal){ return vecVal<100&& vecVal>=findVal;}));

    TEST_list_show("newList1              : ",newList1);
    newList1.insert(3,333);
    TEST_list_show("newList1.insert(3,333): ",newList1);

    TEST_list_show("newList1        : ",newList1);
    newList1.insert(newList1.size(),NewList::value_type(666));
    TEST_list_exec("newList1.last() : ",newList1.last());

    newList1.prepend(333);
    TEST_list_exec("newList1.first(): ",newList1.first());
    TEST_list_show("newList1        : ",newList1);

    newList1.clear();
    TEST_list_show("newList1  : ",newList1);
    TEST_list_show("newList3  : ",newList3);
    TEST_list_show(" stdSet: ",stdSet);
    TEST_list_show("stdList: ",stdList);
    newList1.push_back(11);
    newList1.push_back(newList3);
    newList1.push_back(stdSet);
    newList1.push_back(stdList);
    newList1.push_front(444);
    TEST_list_show("newList1  : ",newList1);

    newList1.remove(11);
    TEST_list_show("newList1 remove-1 : ",newList1);
    newList1.remove(15,[](int vecVal,int findVal){ return vecVal < findVal+2 && vecVal >= findVal-2;});
    TEST_list_show("newList1 remove-2 : ",newList1);
    newList1.removeRange(3,6);
    TEST_list_show("newList1 remove-3 : ",newList1);
    newList1.removeFirst();
    newList1.removeLast();
    newList1.removeAt(3);
    TEST_list_show("newList1 remove-4 : ",newList1);
    TEST_list_exec("newList1.size()     : ",newList1.size());
    newList1.removeAll();
    TEST_list_show("newList1 removeAll  : ",newList1);
    TEST_list_exec("newList1.size()     : ",newList1.size());

    newList1 = newList3;
    TEST_list_show("newList1=newList3      : ",newList1);
    newList1.replace(3,333);
    TEST_list_show("newList1.replace(3,333): ",newList1);

    TEST_list_show("newList3               : ",newList3);
    newList1.swap(newList3);
    TEST_list_show("newList1.swap(newList3) : ",newList1);
    TEST_list_show("newList3               : ",newList3);
    newList1.swap(3,7);
    TEST_list_show("newList1.swap(3,7) : ",newList1);

    TEST_list_exec("newList1.takeAt(3)   : ",newList1.takeAt(3));
    TEST_list_exec("newList1.takeFirst() : ",newList1.takeFirst());
    TEST_list_exec("newList1.takeLast()  : ",newList1.takeLast());
    TEST_list_exec("newList1.value(7)    : ",newList1.value(7));


    TEST_list_show("newList5      : ",newList5);
    TEST_list_show("stdSet        : ",stdSet);
    TEST_list_show("stdList       : ",stdList);
    TEST_list_show("stdVec1       : ",stdVec1);
    stdSet = newList5.toStdSet();
    stdVec1 = newList5.toStdVec();
    stdList = newList5.toStdList();
    TEST_list_show("stdSet        : ",stdSet);
    TEST_list_show("stdList       : ",stdList);
    TEST_list_show("stdVec1       : ",stdVec1);

更多資料

  本文完整源碼:https://github.com/deargo/cpphelper

  更多學習資料:https://blog.csdn.net/aguoxin

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章