排序算法 C++如何实现堆排序

堆排序基本思路

1、理解堆的特点,父节点总是大于(在总是小于)孩子节点。
父节点总是大于孩子节点的完全二叉树称为大根堆。(本文以大根堆为例)
父节点总是小于孩子节点的完全二叉树称为小根堆。
2、每次把堆的最上面的值拿出来,再调整余下节点为新的堆。
3、拿n-1次后则完成排序。

heapSort初步实现:

1、建堆
2、取顶
3、调整
重复2、3的步骤n-1次完成排序

void heapSort(vector<int>&vec){
	createHeap(vec);
	for(int loc=vec.size()-1;loc>0;--loc){
	swap(vec[loc],vec[0]);
	adjustHeap(vec,0,loc-1);
	}
}

剩下的那么接下来的问题就是如何建堆和调整堆。

如何建堆

思路:
1、叶子节点没子节点,可视作堆。完全二叉树最后一层叶子数为总个数的1/2或1/2-1;
2、则需要从第一个叶子节点的前一个节点开始调整,以每个节点为顶点的堆。设这节点为s,即已有[s+1,s+2.....n]是已完成的堆,
3、调整s到根节点的每一个节点则完成堆的建立

createHeap实现

void createHeap(vector<int>&vec){
	unsigned size=vec.size();
	for(int i=size/2-1;i>=0;--i)
		adjustHeap(vec,i,size-1);
	
}

如何调整堆

思路:
1、与两个子节点中最大的数比大小
2、如果大于两个子节点,则已完成调整。(因为调整堆,是已有【s+1…n】堆基础)
3、如果小于子节点,则与子节点互换位置,重复上面的过程。

调整堆实现

void adjustHeap(vector<int>&vec,int i,int loc){
	for(int j=2*i+1;j<=loc;j=j*2+1)
	{
		if(j<loc&&vec[j]<vec[j+1]) j++;
		if(vec[j]<=vec[i]) break;
		swap(vec[j],vec[i]);i=j;			
	}
	
}

附录( 包括测试的主函数的完整代码)

#include<iostream>
#include<vector>
using namespace std;
void adjustHeap(vector<int>&vec,int i,int loc){
	for(int j=2*i+1;j<=loc;j=j*2+1)
	{
		if(j<loc&&vec[j]<vec[j+1]) j++;
		if(vec[j]<=vec[i]) break;
		swap(vec[j],vec[i]);i=j;			
	}
	
}
void createHeap(vector<int>&vec){
	unsigned size=vec.size();
	for(int i=size/2-1;i>=0;--i)
		adjustHeap(vec,i,size-1);
	
}
void heapSort(vector<int>&vec){
	createHeap(vec);
	for(int loc=vec.size()-1;loc>0;--loc){
	swap(vec[loc],vec[0]);
	adjustHeap(vec,0,loc-1);
	}
}
int main(){
	vector<int>vec={65,66,55,33,22,10,22,1,3,5,7,3,4,2,0,4,3,2,8,7,6};
	heapSort(vec);
	for(int val:vec)
		cout<<val<<" ";
       cout<<endl;	
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值