heap能够用来排序,其调整大顶堆或小顶堆的方法能够作为priority queue实现的低层机制,但细看了《STL源码剖析》中的有关Heap一节,才知道STL中并没有把heap作为一种容器组件,heap的实现亦需要更低一层的容器组件(诸如list,array,vector)作为其底层机制。Heap是一个类属算法,包含在algorithm头文件中。
在《数据结构》的课时学习中,我们知道heap的图其实是一颗完全二叉树,基于其特征,可以用array来存储,且根据其需要,分为大顶堆和小顶堆。然而,在STL中,由于array的缺点(无法动态改变大小),改用vector代替array,并且只供应大顶堆max-heap。
在此又不得不粗略提一下vector容器的实现原理。
Vector容器的数据结构实际就是一段线性连续空间,用迭代器start和finish分别指向连续空间中目前被使用的范围(就好像队列queue的头尾指针一样),就个人认为vector其实是和array几乎一样的存在。但vector为了实现快速的内存分配,在分配空间容量时会比当前所需空间多一些,用于存放新添加的元素;当预留空间用完时,以加倍当前容量的分配策略实现重新分配(事实上容量的重新分配需要“重新配置、元素移动、释放原空间”的过程,事实证明这个策略所变现出来的性能非常好)。然后,在基于array和快速内存分配的基础上,应用了迭代器begin、end和end_of_storage(连续可用空间的尾),提供了首尾标示、大小、容量、空容器、标注([ ])运算等等的机能。
在STL中为堆heap的创建和操作提供了4种算法:make_heap,pop_heap,push_heap和sort_heap。其中:
make_heap:利用区间[first,last)中的元素构造一个heap。
函数原型:void make_heap(first,last)
void make_heap(first,last ,compare_fuction)。
pop_heap: 假定区间[first,last)中已包含一个堆,将first位置和last-1位置上的值交换,重新把[first,last-1)调整为一个堆。
函数原型:void pop_heap(first,last);
void pop_heap(first,last,compare_fuction)。
push_heap: 假定区间[first,last-1)已经包含了一个堆,把区间[first,last)调整为一个堆(从而 把last-1位置上的元素压入堆。
函数原型:void push_heap(first,last);
void push_heap(first,last,compare_fuction).
sort_heap: 对存储在堆中的元素进行排序。
函数原型:void sort_heap(first,last);
void sort_heap(first,last,compare_fuction)
对比之前做过的堆排序的实验,感觉STL中的heap优化并不比教材里面介绍的强多少。想想也应该是,那算法思想是一模一样的,但在代码的实现上,STL中做到了规范化。其次,STL中应用了vector作为heap的底层机制,克服了教材中用array存储空间无法动态改变大小的缺点。其三,STL中关于heap的四个算法都实现了函数重载,虽然STL中关于heap默认调整成的是大顶堆,但却可以让用户利用自定义的compare_fuction函数实现大顶堆或小顶堆。其四,heap的低层机制vector本身就是一个类模板,heap基于vector便实现了对各种数据类型(无论基本数据类型还是用户自定义的数据类型)的堆排(前提是用户自定义的数据类型要提供比较机制compare_fuction函数)。
参考阅读书籍:《STL源码剖析》、《C++Primer中文版》、
《标准模板库自修教程与参考手册:STL进行C++编程》