有可能是全网最易理解的有关【堆排序】的博客

这次想写一下堆排序,之前遇到过好多次有关堆排序的问题,无论是编程还是选择题。但是对这个堆排序一直是稀里糊涂,一个原因网上好多博客写的烂,众说纷纭,各执一词,还有一个原因是自己没有真正想要搞懂一个问题,真正搞透问题。

好了废话不多说开始讲解这次的主角堆排序

堆排序步骤

堆排序的步骤主要是三个:

  • 将序列构建成堆,然后整理这个堆,如果最终需要得到升序->大顶堆,降序->小顶堆
  • 将堆顶元素和末尾元素互换,将最大元素放到堆的最后
  • 然后调整这个堆,将除了最后一个元素之外的其他元素按照堆的顺序进行整理,然后再将堆顶元素和最后一个元素(除了刚刚已经被放在最后一个的元素)进行互换位置。

这个地方有很多地方都是坑:
一个就是:
首先必须按照最后的排序要求构建大顶堆还是小顶堆!!!
首先必须按照最后的排序要求构建大顶堆还是小顶堆!!!
首先必须按照最后的排序要求构建大顶堆还是小顶堆!!!

第二个就是:
(这个步骤非常重要)构建大顶堆,小顶堆的方法:从最后一个非叶子节点(这个节点的位置非常有意思:如果节点数为奇数:n/2-1; 如果节点数是偶数:n/2)开始调整,将这个节点和自己的两个子节点进行比较,将这三个节点中最大或者最小的放在根节点处,从右向左,从下向上,依次整理过去。

第三个就是:
互换堆顶和末尾节点之后,末尾节点就不考虑了(排除在后续操作之外了)

复杂度

堆排序的平均时间复杂度、最好情况时间复杂度、最差情况时间复杂度都是O(nlog2n)O(nlog_2n)
空间复杂度:O(1)O(1)
堆排序是一种不稳定的排序。

C++实现代码

//调用heap_sort,其中data为待排序的数组,heapsize为数组长度
void heapsort(int data[],int heapsize){
	//堆排序算法实现主体:先用build_max_heap将输入数组构造成大顶堆
	//将data[0]和堆的最后一个元素交换
	//继续进行调整
build_max_heap(data,heapsize);
for(int i=heapsize-1;i>0;i--){
	int t=data[0];
	data[0]=data[i];
	data[i]=t;
	max_heapify(data,0,i);
	}
}
void build_max_heap(int data[],int heapsize){
//建堆的过程,通过自底向上地调用max_heapify来将一个数组data[1...n]变成一个大顶堆
//只对除了叶子节点之外的节点进行调整
for(int i=heapsize/2-1;i>=0;i--)
	max_heapify(data,i,heapsize);
}
void max_heapify(int data[],int i,int heapsize){
	//以某个节点为根节点的子树进行调整,调整为大顶堆
	int l=2*i+1;
	int r=2*i+2;
	int largest =i;
	if(l<heapsize && data[l]>data[i]){
	 largest =l;
	}
	if(r<heapsize && data[r]>data[largest]){
	largest =r;
	}
	if(largest!=r){
	int temp=data[largest];
	data[largest]=data[i];
	data[i]=temp;
	max_heapify(data,largest,heapsize);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章