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;
}

优质内容筛选与推荐>>
1、Ubuntu 10.10+安装Firefox 4.0正式版
2、Android开发指南中文版(四)Processes and Threads
3、Dynamic CRM 2013学习笔记(五)禁止修改、删除审批通过后的单据
4、java web 中有效解决中文乱码问题-pageEncoding与charset区别, response和request的setCharacterEncoding 区别
5、artTemplate教程


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn