zoukankan      html  css  js  c++  java
  • c++ STL 学习记录 草稿。

    非常丑陋的尝试实现stl。慢慢修改吧。

    1)简单实现 vector和list。

    2)思索如何开始编写算法。

      1,所有容器继承一个抽象容器。那么算法就可以使用抽象基类的next方法来遍历元素。 容器间耦合太高,放弃。

      2,所有容器的元素T继承一个基类,算法使用基类的next方法来遍历元素。应该是可以的。做到一半,实现多态时,必须太多指针样子,好像跟stl的使用相差太远。看书发现stl是用模板模拟多态。或者说是模板的正宗,优雅的多态形式。

      3,使用模板的更优雅的多态思想来实现容器的迭代器。

    3)后面的改进,在于迭代器修改为pointerlike的类。还有书上谈到把各自的迭代器放入到容器类中?以免迭代器暴露太多容器细节。为什么不可以用容器的public方法?

    第一版

    main

    #include <iostream>
    #include "myvecotr.h"
    #include "al.h"
    #include <algorithm>
    #include <vector>
    #include "mylist.h"
    
    using namespace std;
    
    class Book
    {
    public:
        Book(int _id,const string& _name):id(_id),name(_name){}
        int GetInt()
        {
            return id;
        }
        string GetName()
        {
            return name;
        }
    
        bool operator==(const Book& rhg)
        {
            bool ret=false;
            if(rhg.id==this->id && rhg.name==this->name)
            {
                ret=true;
            }
            return ret;
        }
    
    private:
        int id;
        string name;
    };
    
    int main()
    {
        Book cc(1,"c++");
        Book cc2(5,"c");
        Book cc3(3,"c#");
    
        cout<<"*************stl*********************"<<endl;
        vector<Book> books2;
        books2.push_back(cc);
        books2.push_back(cc2);
        books2.push_back(cc3);
    
        vector<Book>::iterator myit=books2.begin();
        cout<<myit->GetName()<<endl;
    
    
        cout<<"*************list*********************"<<endl;
        MyList<Book> bookList;
        bookList.push_back(cc);
        bookList.push_back(cc2);
        bookList.push_back(cc3);
    
        cout<<bookList.GetHead()->GetV()->GetName()<<endl;
    
        ListIterator<Book> FF= myFind(bookList.getFirstIterator(),bookList.getIterator(2),cc3);
        cout<<FF.GetP()->GetV()->GetName()<<endl;
    
    
        myVector<Book> books;
        books.push_back(cc);
        books.push_back(cc2);
        books.push_back(cc3);
    
    
        cout<<"*************vector*********************"<<endl;
        myVector<Book>::iterator rnt=myFind(books.GetBegin(),books.GetEnd(),cc2);
    
        cout<<rnt->GetName()<<endl;
        return 0;
    }

    mylist.h

    #ifndef MYLIST_H_INCLUDED
    #define MYLIST_H_INCLUDED
    #include <memory>
    #include <stdexcept>
    #include <iostream>
    
    using namespace std;
    
    ////////////////////listnode.
    template<typename T>
    class ListNode
    {
    public:
        ListNode( T*,ListNode*);
        void SetNext(ListNode*);
        ListNode* GetNext();
        bool IsEmpty();
        T* GetV();
    
    
    private:
    
        T* value;
        ListNode* next;
    };
    
    template<typename T>
    ListNode<T>::ListNode( T* v,ListNode* n):value(v),next(n){}
    
    template<typename T>
    void ListNode<T>::SetNext(ListNode* n)
    {
        next=n;
    }
    
    template<typename T>
    ListNode<T>* ListNode<T>::GetNext()
    {
        return next;
    }
    
    template<typename T>
    bool ListNode<T>::IsEmpty()
    {
        if(value==0 && next==0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    
    template<typename T>
    T* ListNode<T>::GetV()
    {
        return value;
    }
    
    /////////////////////////////////list iterator
    
    
    //1)必须有正确的+号操作和!=操作.2)必须有全局的元素和迭代器==的重载.
    
    template<typename T>
    class ListIterator
    {
    public:
        ListIterator(ListNode<T>* v):myP(v){}
        ListIterator operator+(int index)
        {
            ListNode<T>* pListNode=myP;
            for(int i=0;i!=index;++i)
            {
    
                if(pListNode->GetNext()!=0)
                {
                    pListNode=pListNode->GetNext();
                }
                else
                {
                    break;
                }
            }
            return ListIterator(pListNode);
        }
    
        bool operator!=(const ListIterator& rht)
        {
            return myP!=rht.myP;
        }
        ListNode<T>* GetP()
        {
            return myP;
        }
    private:
        ListNode<T>* myP;
    };
    
    template<typename T>
    bool operator==( ListIterator<T>& lht,  T& rht)
    {
        return rht==*(lht.GetP()->GetV());
    }
    
    
    
    
    /////////////////////////////////mylist
    
    
    template<typename T>
    class MyList
    {
    public:
        MyList():head(0),size(0){}
        void push_back(const T& v)
        {
            ListNode<T>* tempNode=new ListNode<T>(new T(v),0);
            if(head==0)
            {
                head=tempNode;
                ++size;
            }
            else
            {
                ListNode<T>* temp=head;
                while(temp->GetNext()!=0)
                {
                    temp=temp->GetNext();
                }
                temp->SetNext(tempNode);
                ++size;
            }
        }
    
        ListNode<T>* GetHead()
        {
            return head;
        }
    
    
        ListIterator<T> getFirstIterator()
        {
            return ListIterator<T>(head);
        }
    
        ListIterator<T> getIterator(int i)
        {
            ListNode<T>* rnt=0;
            if(i>=0)
            {
                ListNode<T>* temp=head;
    
                for(int index=0;index!=i;++index)
                {
                    ListNode<T>* temp2=temp->GetNext();
                    if(temp2!=0)
                    {
                        temp=temp2;
                        cout<<temp<<endl;
                    }
                    else
                    {
                        break;
                    }
                }
    
                rnt=temp;
            }
    
            return ListIterator<T>(rnt);
        }
    
    
        ~MyList()
        {
            ListNode<T>* temp=head;
            while(temp!=0)
            {
                ListNode<T>* del=temp;
                temp=temp->GetNext();
                delete del->GetV();
                delete del;
            }
        }
    private:
        int size;
        ListNode<T>* head;
    };
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    #endif // MYLIST_H_INCLUDED

    myvector.h

    #ifndef MYVECTOR_H_INCLUDED
    #define MYVECTOR_H_INCLUDED
    //allocator<T> a;                           定义一个T类型的allocator对象。
    //a.allocate(n);                            申请n个T大小的,未分配的空间。类似(T*) malloc(sizeof(T)*n)
    //a.deallocate(p,n)                         释放内存,p为T*,n为释放的T类型对象的数量。注意:T类型对象本身,如有需要释放的资源,必须先释放,a.deallocate(p,n)只是释放对象本身的内存,而对象的建立又额外申请的资源,需要另外处理。
    //a.construct(p,t)                          复制构造,用t来复制构造。相当于 new (p) T(t),这个是placement new的用法  new(place_address) type(initializer-list)
    //a.destroy(p)                   调用pd对象的析构函数。
    //uninitialized_copy(startit,endit,it)      startit,endit :要复制的开始迭代器地址和结束地址。it:要复制的迭代器地址。
    //uninitialized_fill(startit,endit,obj)     startit,endit :要复制的开始迭代器地址和结束地址。it:要复制的对象。 使用复制构造函数填充内存
    //uninitialized_fill_n(startit,endit,obj,n) startit,endit :要复制的开始迭代器地址和结束地址。it:要复制的对象。 n,要复制的数量。 使用复制构造函数填充内存
    
    //因为是模板,有类型参数,类的方法编译的时候,不能确定所占用的栈大小.必须使用的时候才能确定,而且不同的T类型,有不同的方法地址.所以申明定义放到一起
    #include <memory>
    #include <stdexcept>
    #include <iostream>
    #include "myitertor.h"
    using namespace std;
    
    template<typename T>
    class myVector{
    public:
    
        //如果分配错误呢?
        myVector():pbegin(myalloc.allocate(defautlSize)),pend(pbegin),pcapcity(pbegin+defautlSize),Vsize(0),Vcapcity(defautlSize){}
    
        typedef T* iterator;
    
        void push_back(const T& _obj)
        {
            if(pend>=pcapcity)
            {
                T* pTempAlloc=myalloc.allocate(Vcapcity*2);
                T* pPrep=pbegin;
                if(pTempAlloc!=0)
                {
                    uninitialized_copy(pbegin,pend,pTempAlloc);
                    pbegin=pTempAlloc;
                    pend=pbegin+Vsize;
                    pcapcity=pbegin+(Vcapcity*2);
                    Vsize=Vsize;
                    Vcapcity+=Vcapcity;
    
                    //清理原资源.
                    destroyS(pPrep,pPrep+Vsize,pPrep+Vsize);
                }
                else
                {
                    throw runtime_error("error allocator!");
                }
            }
    
            myalloc.construct(pend,_obj);
            ++pend;
            ++Vsize;
        }
        void erase(unsigned int index)
        {
            if(index>=0&& index<Vsize)
            {
                myalloc.destroy(pbegin+index);//手动调用对象析构
                for(int i=index+1;i!=Vsize;++i)//往前覆盖.最后一个对象占用的内存,不管了.pend往前移动就好.
                {
                    uninitialized_copy(pbegin+i,pbegin+i+1,pbegin+i-1);
                }
                --Vsize;
                --pend;
            }
            else
            {
                throw runtime_error("index over range.");
            }
    
        }
        ~myVector()
        {
            destroyS(pbegin,pend,pcapcity);
        }
        myVector(const myVector& _obj)
        {
            pbegin=myalloc.allocate(_obj.Vcapcity);
            pend=pbegin+_obj.Vsize;
            pcapcity=pbegin+_obj.Vcapcity;
            Vsize=_obj.Vsize;
            Vcapcity=_obj.Vcapcity;
            uninitialized_copy(_obj.pbegin,_obj.pend,pbegin);
        }
    
    
        myVector& operator=(const myVector& _obj)
        {
            if(&_obj!=this)
            {
                destroyS(pbegin,pend,pcapcity);
                pbegin=myalloc.allocate(_obj.Vcapcity);
                pend=pbegin+_obj.Vsize;
                pcapcity=pbegin+_obj.Vcapcity;
                Vsize=_obj.Vsize;
                Vcapcity=_obj.Vcapcity;
    
                uninitialized_copy(_obj.pbegin,_obj.pend,pbegin);
            }
            return *this;
        }
    
    
    
        int size()
        {
            return pend-pbegin;
        }
    
        int capcity()
        {
            return pcapcity-pbegin;
        }
    
        void showInfo()
        {
            cout<<"pbegin:"<<(void *)pbegin<<". size:"<<Vsize<<". capcity"<<Vcapcity<<". pend:"<<(void *)pend<<endl;
            T* pb=pbegin;
            for(pb;pb!=pend;++pb)
            {
                cout<<*pb<<endl;
            }
        }
    
        T& operator[](int index)
        {
            return *(pbegin+index);
        }
    
    
    
        T* GetBegin()
        {
            return pbegin;
        }
        T* GetEnd()
        {
            return pend;
        }
    
    
    
    private:
        static allocator<T> myalloc;
        const static int defautlSize=3;
        T* pbegin;
        T* pend;
        T* pcapcity;
        unsigned int Vcapcity;
        unsigned int Vsize;
    
    
    
        void destroyS(T* PS,T* PE,T* PC)
        {
            T* pb=PS;
            for(pb;pb!=PE;++pb)
            {
                myalloc.destroy(pb);//仅仅调用析构函数.
            }
            myalloc.deallocate(PS,PC-PS);
        }
    
    };
    
    //int book::pid=6
    template<typename T>
    allocator<T> myVector<T>::myalloc=allocator<T>();
    
    template<typename T>
    bool operator==(T* a,T v)
    {
        bool rnt;
        if(*a==v)
        {
            rnt=true;
        }
        else
        {
            rnt=false;
        }
        return rnt;
    }
    
    #endif // MYVECTOR_H_INCLUDED

    al.h

    #ifndef AL_H_INCLUDED
    #define AL_H_INCLUDED
    
    #include "myitertor.h"
    
    //1)必须有正确的+号操作和!=操作.2)必须有全局的元素和迭代器==的重载.
    
    
    template<typename T,typename MyInputIterator>
    MyInputIterator myFind(MyInputIterator start,MyInputIterator end, T& value)
    {
        for(start;start!=end;start=start+1)
        {
            if(start==value)//
            {
                break;
            }
        }
        return start;
    }
    
    #endif // AL_H_INCLUDED

    hashtable:

    自己写的 hashtable,不过hash函数还是stl的hash ,而且冲突时的链表也是直接使用stl的list。

    之前写了几次总放弃,重要是考虑太多,自己造hash的轮子,总感觉不适用,一直停在那里。又考虑list 的具体细节。还要和这里配合。

    感觉造轮子前,先使用木头,而不要先造斧头,去砍树。这样造个轮子都要很耗精力。

    等轮子造好了,再去造斧头。再去造炉子,再去造火。要不然会总停在某个点上。

    造轮子的目的其实是理解。方便选择适合的场景使用适当的数据结构。

    最终的目的是使用标准的轮子。而不是自己的轮子。

    从难学。从易用。切记。。。

    #include <iostream>
    #include "stdio.h"
    #include <memory>
    #include <unistd.h>
    #include <thread>
    #include <vector>
    #include <algorithm>
    #include <memory.h>
    #include <map>
    #include <list>
    #include <ext/hash_map>
    
    using namespace std;
    using namespace __gnu_cxx;
    
    struct Good
    {
        int gid;
        string goodName;
        int value;
    };
    
    namespace __gnu_cxx  
    {
        template<> struct hash<string>
        {
            size_t operator()(const string& s) const
            {
                return   __stl_hash_string(s.c_str());
            }
        };
    }
    
    template<typename T>
    class HashTable
    {
    public:
        class Hashv
        {
          public:
            string key;
            T value;
        };
    
        HashTable(int32_t v)
        {
            ht=new list<Hashv>[v];
            ht_size=v;
        }
        
        int32_t hash(const string& _key)
        {
            std::hash<string> sh;
            size_t hv= sh(_key);
            hv=hv%ht_size;
            return hv;
        }
        
        bool Add(const string& key,const T& _v)
        {
            int32_t _hash_index=hash(key);
            Hashv temp;
            temp.key=key;
            temp.value=_v;
            ht[_hash_index].push_back(temp);
            return true;
        }
        
        T Search(string _key)
        {
            int32_t _hash_index=hash(_key);
            T ret;
    
            if(ht[_hash_index].size()==1)
            {
                ret= ht[_hash_index].begin()->value;
            }
            else
            {
                for(auto obj : ht[_hash_index])
                {
                    if(obj.key==_key)
                    {
                        ret= obj.value;
                    }
                }
            }
            
            return ret;
        }
        
       ~HashTable()
       {
           delete[] ht;
       }
    private:
        list<Hashv> * ht;
        int32_t ht_size;
    };
    
    
    
    void main2();
    int main()
    {
        
        //map
        map<int,Good> good_buff;
        
        for(int i=0;i<10000;++i)
        {
            Good temp;
            temp.gid=i;
            temp.goodName="test";
            temp.value=i%100+1;
            
            good_buff.insert(map<int,Good>::value_type(temp.gid,temp));
        }
        
        int gid=405;
        
        if(good_buff.find(gid)!=good_buff.end())
        {
            cout<<good_buff[gid].value<<endl;
        }
        
        
        
        
        //simple hashtable
        HashTable<Good> myhash(100);
        Good temp;
        temp.gid=3;
        temp.goodName="test";
        temp.value=31;
        
        myhash.Add("3",temp);
        
        Good temp2;
        temp2.gid=4;
        temp2.goodName="test";
        temp2.value=41;
        
        myhash.Add("4",temp2);
        
        Good ss=myhash.Search("4");
        
        cout<<ss.value<<endl;
        
       //stl hash map.
       
       hash_map<string,Good> stlhash;
       
       stlhash.insert(hash_map<string,Good>::value_type("test",temp));
       stlhash.insert(hash_map<string,Good>::value_type("test2",temp));
       
       hash_map<string,Good>::iterator ss2=stlhash.find("test");
       cout<<ss2->second.value<<endl;
        
        int cmd;
        cin>>cmd;
    }
  • 相关阅读:
    课程一(Neural Networks and Deep Learning),第三周(Shallow neural networks)—— 1、两层神经网络的单样本向量化表示与多样本向量化表示
    LaTeX技巧:如何高效地将LaTeX代码转为Word公式
    Python使用闭包结合配置自动生成函数
    批量发货阻塞启示:深挖系统薄弱点
    Java8函数式编程探秘
    碎碎念集萃六
    改善代码可测性的若干技巧
    使用yaml+groovy实现Java代码可配置化
    JsonPath:从多层嵌套Json中解析所需要的值
    一个略复杂的数据映射聚合例子及代码重构
  • 原文地址:https://www.cnblogs.com/lsfv/p/6218962.html
Copyright © 2011-2022 走看看