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.应用间通信 “共享”合约是用户可以在应用之间快速交换数据的一种方式. 例如,用户可能希望使用社交网络应用与其好友共享网页,或者将链接保存在笔记应用中以供日后参 ...
随机推荐
- redmine常见问题
1.测试Pop3邮件收件任务:rake redmine:email:receive_pop3 RAILS_ENV="production" host=pop.cecgw.cn po ...
- Ubuntu16.04 802.1x 有线连接 输入账号密码,为什么连接不上?
ubuntu16.04,在网络配置下找到802.1x安全性,输入账号密码,为什么连接不上? 这是系统的一个bug解决办法:假设你有一定的ubuntu基础,首先你先建立好一个不能用的协议,就是按照之 ...
- c++实验,需要的人都知道是啥
利用点.线.面的基本知识,声明Point,Line,Friangle,PolyAngle四个类,完成以下功能.Point类功能://实验88888(1) 移动一个点:(2) 显示一个点:(3) 可计算 ...
- 彻底卸载Oracle
彻底卸载Oracle 用Oracle自带的卸载程序不能从根本上卸载Oracle,从而为下次的安装留下隐患,那么怎么才能完全卸载Oracle呢?那就是直接注册表清除,步骤如下: 1. 开始->设置 ...
- paper 123: SVM如何避免过拟合
过拟合(Overfitting)表现为在训练数据上模型的预测很准,在未知数据上预测很差.过拟合主要是因为训练数据中的异常点,这些点严重偏离正常位置.我们知道,决定SVM最优分类超平面的恰恰是那些占少数 ...
- Ado.net 数据库读取文件
string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString; using ...
- mvc 中的 [ChildActionOnly] 和 [NonAction]
首先,NonAction表示它不是一个真正的Action,而是一个普通方法, 就像我们定义一个普通的方法那样,返回值可以任意定义; 而 ChildActionOnly表示它只能在View中通过Htm ...
- 阿里云CDN刷新预热接口
阿里云OSS映射的文件地址需要即时访问到最新数据,需要即时调用CDN的刷新预热类接口 RefreshObjectCaches 刷新接口. 参考官方接口文档资料:https://help.aliyun. ...
- TortoiseGit使用手册
1 安装 1.1 32位系统 1.2 64位系统 2 配置 2.1 设置语言 2.2 配置用户信息 2.3 生成ssh-key(仅限第一次使用) 2.4 初始化仓库(尚未使用git管理的项目) 2.5 ...
- github开发
从0开始学习 GitHub 系列之「初识 GitHub」 从0开始学习 GitHub 系列之「加入 GitHub」 从0开始学习 GitHub 系列之「Git 速成」 从0开始学习 GitHub 系列 ...