堆排序也就是一个简单的完全二叉树,满足的规则是每个父节点大于(小于)子节点,一般通过线性队列来实现,所以一般是通过数组来实现的。
基本的排序步骤是:
1.创建堆 CreateHeap
2.依次的取出头节点(也就是最大值或者最小值) deleteMax
3.把取出的值放到一个新的容器中,当然我们为了空间复杂度较小 可以直接在原有的容器末尾插入。
实现:
HeapSort.h
//堆排序的实现,空间复杂度为N,时间复杂度为N*logN。这里对对于可随机访问的容器的操作
//而且此次排序是 从小到大的排序,如果需要改变排序规则,则需要重载Object对象的>和<操作符
#ifndef ___HEAP_SORT_H
#define ___HEAP_SORT_H
namespace zk_sima
{
template<typename Iterator,typename Object>
void CreateHeap(Iterator first,Iterator last,Object)
{
int pos=0;
for(Iterator iter=first;iter!=last;++iter,++pos)
{
Object obj=*iter;
int childPos=pos;
int parentPos=(pos-1)/2;
while(parentPos>=0&&parentPos<childPos)
{
if(obj<=*(first+parentPos))
{
*(first+childPos)=obj;
break;
}
else
{
*(first+childPos)=*(first+parentPos);
*(first+parentPos)=obj;
childPos=parentPos;
parentPos=(parentPos-1)/2;
}
}
}
}
template<typename Iterator,typename Object>
Object deleteMax(Iterator first,Iterator last,Object obj)
{
int interval=last-1-first;
if(interval<0)
return *first;
else
{
Object obj=*(last-1);
*(last-1)=*first;
*first=obj;
int parentPos=0;
int childPos=2*parentPos+1;
while(childPos<=interval-1)
{
if(childPos==interval-1)
{
if(obj>=*(first+childPos))
break;
else
{
*(first+parentPos)=*(first+childPos);
*(first+childPos)=obj;
break;
}
}
childPos=*(first+childPos)>*(first+childPos+1)?childPos:(childPos+1);
if(obj>*(first+childPos))
break;
else
{
*(first+parentPos)=*(first+childPos);
*(first+childPos)=obj;
parentPos=childPos;
childPos=2*childPos+1;
}
}
}
return *(last-1);
}
template<typename Iterator,typename Object>
void HeapSort(Iterator first,Iterator last,Object)
{
CreateHeap(first,last,*first);
for(int i=0;i!=last-first;++i)
{
deleteMax(first,last-i,*first);
}
}
template<typename Iterator>
void HeapSort(Iterator first,Iterator last)
{
return HeapSort(first,last,*first);
}
}
#endif