堆排序的实现与分及测试

头文件如下:

//《对于任何算法的分析,首先要进行具体的分析,这样才能下手:
// 比如,可以通过图形具象化,代码实现一下,体验一下,任何时候
// 都要尽量避免作抽象思维。》


/*堆排序
 * 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;
}



代码已测试,复制粘贴即可运行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值