头文件如下:
//《对于任何算法的分析,首先要进行具体的分析,这样才能下手:
// 比如,可以通过图形具象化,代码实现一下,体验一下,任何时候
// 都要尽量避免作抽象思维。》
/*堆排序
* 1、将一个无序的序列构建成最大堆(构造初始堆):
* 1.1、从最后一个非叶子节点i开始,以此节点作为堆顶,构造堆;
* 1.2、将i-1作为下一个堆顶,构造堆;
* 1.3、分别以2*i和2*i+1为参数,对左右子节点进行递归;
* 1.4、退出条件是:递归的两个子节点序列号大于序列大小。
* 2、第一步骤中已经构造出一个符合定义的堆,下面完成排序:
* 2.1、交换堆顶元素和最后一个元素,并将无序序列大小减一;
* 2.2、由于上一步破坏了堆结构,所以需要重复第一步,重新构造堆。
* 2.3、退出条件是:无序序列元素个数为1。
*算法的核心就是第一步:堆的构造。
*/
// 总结:
// 参考网页:http://blog.csdn.net/morewindows/article/details/6967409
// http://www.cnblogs.com/luchen927/archive/2012/03/08/2381446.html
// http://blog.csdn.net/xiaoxiaoxuewen/article/details/7570621
// http://www.cnblogs.com/heyuquan/archive/2014/07/22/heap-sort.html 排序算法的优化
// http://www.cnblogs.com/gaochundong/p/complexity_of_algorithms.html 算法复杂度分析
// 为何相比第一个网址里面实现的堆排序算法,我的算法对1000个数据排序都要1000毫秒呢?
// 以后凡是实现的排序算法都要用数以万记的数据进行排序,并查看运行时间,并作以优化和进一步学习。
// 看来仅仅会写一个一般的排序算法是完完全全不够的,一定要注意效率问题,特别是面试的时候处理大数据的问题。
/* 代码实现后记:
* 1、建立初始堆的时候,堆是下往上的。
* 2、调整堆的时候,是从上往下的。
*/
#ifndef HEAPSORT_H
#define HEAPSORT_H
#include "Common.h"
void HeapAdjust( int *a, int i, int size);
void Adjust_heap( vector<int> &v, int length, int i );
void build_heap( vector<int> &v, int length );
void heap_sort( vector<int> &v);
void HeapSortCppTest();
template<typename T>
class Heap{
private:
vector<T> v;
public:
Heap(vector<T> &v);
void heapSortAlgorithm( );
void buildHeap( );
void adjustHeap( int len, int I );// 序号要从0开始,长度要从1开始
void printHeap();
void heapSet(vector<T> &v);
};
#endif
CPP文件如下:
#include "HeapSort.h"
void HeapAdjust( int *a, int i, int size) //调整堆
{
int lChild = 2*i; //i的左孩子节点
int rChild = 2*i+1;//i的右孩子节点
int max = i;
if( i <= size/2 )
{
if( lChild <= size && a[lChild] > a[max] ){
max = lChild;
}
if( rChild <= size && a[rChild] > a[max] ){
max = rChild;
}
if( max != i )
{
int tmpChg = a[i];
a[i] = a[max];
a[max] = tmpChg;
HeapAdjust(a,i,size);
}
}
}
void Adjust_heap( vector<int> &v, int length, int i )
{
int left = 2*i;
int right = 2*i+1;
int largest = i;
int temp;
while( left < length || right < length )
{
if( left < length && v[largest] < v[left] ){
largest = left;
}
if( i != largest )
{
temp = v[largest];
v[largest] = v[i];
v[i] = temp;
i = largest;
left = 2*i;
right = 2*i+1;
}
else{ break; }
}
}
void build_heap( vector<int> &v, int length )
{
int i;
int begin = length/2-1;
for( i = begin; i>=0; i-- )
{
Adjust_heap(v,length,i);
}
}
void heap_sort( vector<int> &v)
{
int length =v.size();
int temp;
cout<<"before sorted:"<<endl;
cout<<"size="<<v.size()<<" capacity="<<v.capacity()<<endl;
for( int i = 0 ; i < length; i ++ )
{
cout<<v[i]<<" ";
}
cout<<endl;
build_heap(v,length);
while( length > 1 )
{
temp = v[length -1 ];
v[length-1] = v[0];
v[0] = temp;
length--;
Adjust_heap(v,length,0);
}
length =v.size();
cout<<"after sorted:"<<endl;
cout<<"size="<<v.size()<<" capacity="<<v.capacity()<<" length="<<length<<endl;
for( int i = 0 ; i < length; i++ )
{
cout<<v[i]<<" ";
}
cout<<endl;
}
// 堆的调整要从以I为堆顶的元素开始
// 然后依次,对其左右子堆进行队规的调整
// 注意:只需要对发生变动了的左右子堆进行调整即可
template<typename T>
void Heap<T>::adjustHeap( int len, int I )// 序号要从0开始,长度要从1开始
{
int Left = 2*I + 1;
int Right = 2*I + 2;
int Largest = I;
int countA = 0;
if( Left < len || Right < len )//构造出大堆
{
//cout<<countA++<<" ";
//printHeap();
if( Right < len )// 避免越界
{
if( (*this).v[Right] > (*this).v[Largest] )
{
Largest = Right;
} //左右子节点分别处理
}
if( Left < len )
{
if( (*this).v[Left] > (*this).v[Largest] )
{
Largest = Left;
}
}
if( Largest != I )
{
::swap<T>( (*this).v[Largest], (*this).v[I] );
if( Largest == Left ) { adjustHeap( len, Left );}
if( Largest == Right ) { adjustHeap( len, Right );}
}
}
return;
}
template<typename T>
void Heap<T>::buildHeap( )
{
int len = (*this).v.size();
int I = len/2 - 1;
for( int count = I; count >= 0; count-- )
{
adjustHeap( len, count );
}
return;
}
template<typename T>
void Heap<T>::heapSortAlgorithm( )
{
int Count = (*this).v.size();
buildHeap( );
for( ; Count > 0; )
{
::swap<T>( (*this).v[0], (*this).v[Count-1]);
Count--;
adjustHeap( Count, 0 );
}
return;
}
template<typename T>
void Heap<T>::printHeap()
{
cout<<"The current heap is: "<<endl;
for( int i =0; i < (*this).v.size(); i++ ) { cout<< (*this).v[i]<<" "; }
cout<<endl;
return;
}
//注意:1、拷贝构造函数和赋值构造函数的区别;
// 2、何时调用了拷贝函数。
// 3、拷贝构造函数和拷贝函数的区别。
template<typename T>
void Heap<T>::heapSet(vector<T> &v)//在此调用vector的拷贝构造函数
{
(*this).v=v;
return;
}
template<typename T>
Heap<T>::Heap(vector<T> &v)
{
heapSet(v);
}
//测试代码:
/**/
void HeapSortCppTest()
{
clock_t tBegin,tEnd;
vector<int> test(1000,8);
for( int i =0; i < test.size(); i++ )
test[i] = rand()%19999;
/*
test.push_back(10);
test.push_back(5);
test.push_back(8);
test.push_back(2);
test.push_back(17);
test.push_back(77);
test.push_back(71);
test.push_back(72);
test.push_back(37);
test.push_back(47);
test.push_back(67);
test.push_back(97);
test.push_back(723);
test.push_back(71);
test.push_back(723);
test.push_back(74);
test.push_back(71);
test.push_back(70);
test.push_back(79);
*/
Heap<int> heap(test);
//heap.printHeap();
tBegin = clock();
heap.heapSortAlgorithm( );
tEnd = clock();
cout<<"The run time of heapSort is : "<<tEnd-tBegin<<" ms"<<endl;
//heap.printHeap();
return;
}
代码已测试,复制粘贴即可运行。