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(,"c++");
Book cc2(,"c");
Book cc3(,"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(),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 ;
}
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== && next==)
{
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=;i!=index;++i)
{ if(pListNode->GetNext()!=)
{
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(),size(){}
void push_back(const T& v)
{
ListNode<T>* tempNode=new ListNode<T>(new T(v),);
if(head==)
{
head=tempNode;
++size;
}
else
{
ListNode<T>* temp=head;
while(temp->GetNext()!=)
{
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=;
if(i>=)
{
ListNode<T>* temp=head; for(int index=;index!=i;++index)
{
ListNode<T>* temp2=temp->GetNext();
if(temp2!=)
{
temp=temp2;
cout<<temp<<endl;
}
else
{
break;
}
} rnt=temp;
} return ListIterator<T>(rnt);
} ~MyList()
{
ListNode<T>* temp=head;
while(temp!=)
{
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(),Vcapcity(defautlSize){} typedef T* iterator; void push_back(const T& _obj)
{
if(pend>=pcapcity)
{
T* pTempAlloc=myalloc.allocate(Vcapcity*);
T* pPrep=pbegin;
if(pTempAlloc!=)
{
uninitialized_copy(pbegin,pend,pTempAlloc);
pbegin=pTempAlloc;
pend=pbegin+Vsize;
pcapcity=pbegin+(Vcapcity*);
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>=&& index<Vsize)
{
myalloc.destroy(pbegin+index);//手动调用对象析构
for(int i=index+;i!=Vsize;++i)//往前覆盖.最后一个对象占用的内存,不管了.pend往前移动就好.
{
uninitialized_copy(pbegin+i,pbegin+i+,pbegin+i-);
}
--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=;
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+)
{
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()==)
{
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=;i<;++i)
{
Good temp;
temp.gid=i;
temp.goodName="test";
temp.value=i%+; good_buff.insert(map<int,Good>::value_type(temp.gid,temp));
} int gid=; if(good_buff.find(gid)!=good_buff.end())
{
cout<<good_buff[gid].value<<endl;
} //simple hashtable
HashTable<Good> myhash();
Good temp;
temp.gid=;
temp.goodName="test";
temp.value=; myhash.Add("",temp); Good temp2;
temp2.gid=;
temp2.goodName="test";
temp2.value=; myhash.Add("",temp2); Good ss=myhash.Search(""); 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;
}
c++ STL 学习记录 草稿。的更多相关文章
- stl学习记录(1)
Effective STL 中文版学习记录 条款4 判断容器是否为空 使用empty而不是size().size()操作在实现上不是一个时间常数操作条款5 尽量使用区间成员函数代替它们的单元素兄弟.S ...
- stl学习记录(2)
#include <iostream> #include <utility> #include <tuple> #include <complex> # ...
- Matlab 进阶学习记录
最近在看 Faster RCNN的Matlab code,发现很多matlab技巧,在此记录: 1. conf_proposal = proposal_config('image_means', ...
- ###STL学习--函数对象
点击查看Evernote原文. #@author: gr #@date: 2014-08-13 #@email: forgerui@gmail.com 在stl中,函数对象被大量地使用,用以提高代码的 ...
- Effective STL 学习笔记 Item 30: 保证目标区间足够大
Effective STL 学习笔记 Item 30: 保证目标区间足够大 */--> div.org-src-container { font-size: 85%; font-family: ...
- Quartz 学习记录1
原因 公司有一些批量定时任务可能需要在夜间执行,用的是quartz和spring batch两个框架.quartz是个定时任务框架,spring batch是个批处理框架. 虽然我自己的小玩意儿平时不 ...
- Java 静态内部类与非静态内部类 学习记录.
目的 为什么会有这篇文章呢,是因为我在学习各种框架的时候发现很多框架都用到了这些内部类的小技巧,虽然我平时写代码的时候基本不用,但是看别人代码的话至少要了解基本知识吧,另外到底内部类应该应用在哪些场合 ...
- Apache Shiro 学习记录4
今天看了教程的第三章...是关于授权的......和以前一样.....自己也研究了下....我觉得看那篇教程怎么说呢.....总体上是为数不多的精品教程了吧....但是有些地方确实是讲的太少了.... ...
- UWP学习记录12-应用到应用的通信
UWP学习记录12-应用到应用的通信 1.应用间通信 “共享”合约是用户可以在应用之间快速交换数据的一种方式. 例如,用户可能希望使用社交网络应用与其好友共享网页,或者将链接保存在笔记应用中以供日后参 ...
随机推荐
- Java Thread wait, notify and notifyAll Example
Java Thread wait, notify and notifyAll Example Java线程中的使用的wait,notify和nitifyAll方法示例. The Object clas ...
- 代码阅读工具:Source Navigator和Source Insight
(摘自http://www.cnblogs.com/yc_sunniwell/archive/2010/08/25/1808322.html) 一.Source Insight实用技巧: Source ...
- 夺命雷公狗-----React---16--事件操作事件
<!DOCTYPE> <html> <head> <meta charset="utf-8"> <title></ ...
- simvision1 database和invoke
VCD是一种ASCII码的文件,可以直接用gvim来打开.有两种格式:1)Four-state, 2) Extended, 相比较而言,Extended VCD会多一些strength的信息. VC ...
- android 布局学习
各种layout用到的一些重要属性 第一类:属性值为true或false android:layout_centerHrizontal 水平居中 android:layout_centerVertic ...
- PHP 生成验证码
//加载 vendor目录的phpqrcode.类文件 $a = vendor("phpqrcode.qrlib");// 创建目录 echo mkdir(__ROOT__.'/U ...
- QT 网络编程
#include "networkinformation.h" #include "ui_networkinformation.h" networkinform ...
- python获取绝对路径
import osimport sysprint 'os.getcwd()=',os.getcwd()print 'sys.argv=',sys.argvprint 'sys.argv[0]=',sy ...
- oracle表分区、表分析及oracle数据泵文件导入导出开心版
1.先说oracle表分区是什么吧,这样吧我们来举个桃子,栗子太小,我们就不举了,我们来举个桃子. 你有500万份文件,你要把他存在磁盘上,好嘛,我们就一个文件夹,500万分文件在那儿杵着,我们想找到 ...
- Hibernate 基础配置及常用功能(一)
本来是想等全部框架测试完以后再统一发布的,但是随着测试的一点点增加感觉把需要叙述的东西放在一起终将会是一场灾难.所以还是打算分成几章来描述,其中还包括一些有待解决的问题.短期很难腾出时间来仔细阅读Hi ...