《STL源码剖析》阅读笔记1

来源:互联网 发布:网络电缆测试仪上电池 编辑:程序博客网 时间:2024/05/29 19:57

排列组合算法

next_permutation

作用:获得[first,last)所表示序列的下一个排列组合

      如果没有,返回false;

      否则返回true

算法:

1-      从最尾端往前搜索两个相邻元素,零第一个元素为*i,第二个为*ii,并满足:*i<*ii;

2-      再从尾端开始往前检验,找出第一个大于*i的元素,令为*j,对调i,j指向元素;

3-      将ii后的所有元素颠倒

例子

      

char*版本代码:

bool next_permutation(char*first,char*last)

{

if(first==last)return false;//空区间

char *i=first;

++i;

if(i==last)return false;//只有一个元素

i=last;//尾端

--i;

for(;;)

{

char *ii=i;

--i;

if(*i<*ii)

   {

char *j=last;

while(!(*i<*--j));

swap(*i,*j);

reverse(ii,last);

return true;    

}

if(i==first)

     {

   reverse(first,last);

  return false;

   }

}

}

prev_ permutation

算法:

1-尾端往前搜索两个相邻元素,零第一个元素为*i,第二个为*ii,并满足:*i>*ii;

2-端开始往前检验,找出第一个小于素,令为*j,对调i,j指向元素;

3-ii的所有元素颠倒

char*版本:

bool prev_permutation(char*first,char*last)

{

if(first==last)return false;//空区间

char *i=first;

++i;

if(i==last)return false;//只有一个元素

i=last;//尾端

--i;

for(;;)

{

char *ii=i;

--i;

if(*i>*ii)

   {

char *j=last;

while(!(*i>*--j));

swap(*i,*j);

reverse(ii,last);

return true;    

}

if(i==first)

 {reverse(first,last);return false;}

}

}

随机重排数组

random_shuffle

for i=1~n-1

swap(a[i],a[rand()%(i+1)])

快速计算x的n次幂 power()的实现

x^n(n>=0)

template <class T>

T power (T x,int n)

{

if(n==0)return 1;

else

{

  Tresult=1;

if(n&1!=0)//n为偶数

 {//result=x,n=n-1或者n=n&0;

 result=x;n=n&0;

}

//n为奇数或偶数时的公共部分

while(n&1==0)

 {

x=x*x;

n>>=1;

}

result*=x;

 

}

return result;

}

模仿STL的版本

template <class T>

T power (T x,int n)

{

if(n==0)return 1;

else

{

 while((n&1==0))//偶数

{

n>>=1;

x=x*x;

}

T result=x;

n>>=1;

while(n!=0)

 {

x=x*x;

if(n&1!=0)奇数

result=result*x;

n>>=1;

}

result

}

}

heap算法和优先级队列

push_heap(first,last)

pop_heap(first,last){adjust_heap}

sort_heap(first,last){一直使用pop_heap直至没有元素为止}

make_heap(first,last){调用adjust_heap}

建立堆

make_heap(_First,_Last, _Comp)

1-默认是建立最大堆的。

在堆中添加数据

push_heap(_First, _Last)

要先在容器中加入数据,再调用push_heap ()

在堆中删除数据

pop_heap(_First,_Last)

要先调用pop_heap()再在容器中删除数据

堆排序

sort_heap(_First,_Last)

用法

int a[9]={1-9}:

vector<int>myvec(a,a+9);

make_heap(myvec.begin(),myvec.end());

///直接改变myvec

优先级队列=vector+heap算法

构造函数---make_heap算法,make_heap(c.begin,c.end(),comp)

push---------(1,低层容器的push_back插入末端,

2,使用push_heap算法重排heap,   push_heap(c.begin,c.end(),comp)

pop---------(1,重排heap,pop_heap(c.begin,c.end(),comp)

2,底层容器的pop_back()弹出元素,   c.pop_back())

自定义类使用优先级队列

通过对结构体重载operator()

1-   定义函数对象

2-    重新定义operator<函数

例子:      

程序功能是模拟排队过程,每人有姓名和优先级,优先级相同则比较姓名,

开始有5个人进入队列,然后队头2个人出队,再有3个人进入队列,

最后所有人都依次出队,程序会输出离开队伍的顺序。

 



将上面结构体Node改成类

  

   

  

使用set容纳自定义类/结构体

使用set容纳自定义类/结构体

set模板需要3个泛型参数:

template<class T, class C, class A>class set;

第一个T 是元素类型,必选;
第二个C 指定元素比较方式,缺省为 Less<T>, 即使用 < 符号比较;
第三个A 指定空间分配对象,一般使用默认类型。

因此:对于第2个泛型参数

(1) 如果使用默认值,自定义元素类型需要重载<运算操作

(2)不使用默认值,则比较对象必须具有() 操作,即自定义函数对象

bool operator()(const T &a, const T&b)

即自定义一个比较函数/函数对象

map使用自定义类-----看模板参数

所以作为关键字,起码必须有“<”这个比较操作符。

1-int,float,enum,size_t等等简单关键字,都有内置的比较函数,与map搭没什么问题。

2-自定义类型,必须明确定义“<”比较操作符,作为第三个参数。

使用map时,注意以下两点,同时这两点也是改错的方法:

a) 关键字明确定义“<”比较操作符

b) 没有“<”比较操作符,自定义仿函数替代第三个参数Compare,该仿函数实现“()”操作符,提供比较功能。插入时使用

  
使用:
map<pair<int,int>,int,comp>res;
res.insert(make_pair(12,33),33);
res.insert(make_pair(122,333),333);

capacity,size

capacity

容器增长前,能够容纳的元素总数;

只有连续存储的容器才有容量概念(vector,deque,string),list不需要;

size

容器当前存储的元素数量;

注:vector默认的容量初始值,增长规则依赖编译器

vector存储自定义对象

自定义对象必须满足:

1,  默认构造函数(默认或自定义的)

2,  可用的拷贝构造,赋值函数(默认或自定义的)

自己的理解:如果对vector排序的话,还需要定义operator<,==等操作符

deque

双向队列-----双向开口的连续线性空间;

高效的在头尾两端插入和删除元素;

deque的实现

内部会维护一个map(注意!不是STL中的map容器)即一小块连续的空间,该空间中每个元素都是指针,指向另一段(较大的)区域,这个区域称为缓冲区,缓冲区用来保存deque中的数据。因此deque在随机访问和遍历数据会比vector慢。

注意一点。对于dequevector来说,尽量少用erase(pos)erase(beg,end)。因为这在中间删除数据后会导致后面的数据向前移动,从而使效率低下。

与vector比:

1-高效的首段插入/删除,2-内存管理

deque的中find自定义的类型

以调用find()在deque中查找:

对应自定义的类和结构须添加:

booloperator == (const MyClass &other) const 成员函数;

或booloperator ==(const MyClass &one, const MyClass &another)全局函数。

内存泄露

如果容器中含有元素:

则程序退出前须清空调用deque的clear()或~deque(),否则出现内存泄露。

如存储的是指针类型deque<MyClass*>

每个指针对应一个堆内存。

1-则需要使用遍历每一个元素并调用delete *iterator;来释放指针指向内存。

2-然后在清空容器(deque的clear()或~deque())




0 0