排序算法:堆排序

排序算法:堆排序

标签(空格分隔): 选择排序、堆排序


一、堆的特点(分为最大堆和最小堆,这里以最大堆说明)

  • 每个节点最多可以有两个节点
  • 根节点的键值是所有堆节点键值最大者,且每个节点的值都比其孩子节点大
  • 除了根节点没有兄弟节点,最后一个左子节点可以没有兄弟节点,其他节点必须要有兄弟节点

二、堆排序

  • 堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特 点快速定位指定索引的元素.
  • (选择排序工作原理 - 第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置, 然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待 排序的数据元素的个数为零)

三、算法核心思路

将根节点的键值跟最后一个节点键值进行替换,同时堆节点个数减1,从根节点开始调整成最大堆

四、算法实现

#include <iostream>
#include <Windows.h>
using namespace std;
//最大堆实现无序数组排序
#define DEFAULT_CAPACITY 128
#define isLess(a,b)   (a<b)

typedef int DataType;
//最大堆
typedef struct _Heap{
	DataType *arr;      
	int size;           
	int capacity;

}Heap;

static void buildHeap(Heap& heap);//建最大堆
static void adjustDown(Heap& heap,int index);//当前的父节点与子节点形成堆

//初始化最大堆
bool initHeap(Heap& heap,DataType *origin,int size){
	if(!origin){
		return false;
	}
	heap.arr=origin;
	
	heap.capacity=size;
	heap.size=size;
	
	//如果数组有初始化数据
	if(size){
		//1.全部插入构建堆
		
		buildHeap(heap);
		
		return true;
	}else{
		heap.size=0;
		return false;
	}

}

/* 从最后一个父节点(size/2-1 的位置)逐个往前调整所有父节点(直到根节 点), 确保每一个父节点都是一个最大堆,最后整体上形成一个最大堆 */
void buildHeap(Heap& heap){
	//从最后一个非叶子节点开始,遍历,让他与子节点形成堆
	for(int parent=heap.size/2-1;parent>=0;parent--){
		adjustDown(heap,parent);
	}

}

/*判断是否存在大于当前节点子节点,如果不存在 ,则堆本身是平衡的,不需要调整; 如果存在,则将最大的子节点与之交换,交换后,如果这个子节点还有子节点,则要继续 按照同样的步骤对这个子节点进行调整 */
static void adjustDown(Heap& heap,int index){
	DataType cur;//当前待调整的节点
	int child;
	for(int parent=index;parent*2+1<heap.size;parent=child){
		child=parent*2+1;
		//最大堆
		if(child+1<heap.size&&isLess(heap.arr[child],heap.arr[child+1])){
			child++;
		}
		
		if(heap.arr[parent]>=heap.arr[child]){
			break;
		}else{
			cur=heap.arr[child];
			heap.arr[child]=heap.arr[parent];
			heap.arr[parent]=cur;
		}
	}
}

//堆排序算法
void sortHeap(Heap& heap){
	DataType temp;
	while(heap.size>0){
		temp=heap.arr[heap.size-1];
		heap.arr[heap.size-1]=heap.arr[0];
		heap.arr[0]=temp;
		heap.size--;//将根节点排除
		adjustDown(heap,0);//根节点向下调整,形成最大堆
	}
}
//测试代码
int main(void){
	Heap heap;
	int count=0;
	DataType a[]={2,6,21,9,576,34,12,13,0};
	if(!initHeap(heap,a,sizeof(a)/sizeof(a[0]))){
		cout<<"初始化失败"<<endl;
	}else{
		cout<<"初始化成功"<<endl;
	}
	//执行堆排序
	sortHeap(heap);
	cout<<"执行堆排序后:"<<endl;
	cout<<"请输入要输出的元素个数:";
	cin>>count;
	if(count<=sizeof(a)/sizeof(a[0])){
		for(int i=0;i<count;i++){
			cout<<a[i]<<" ";
		}
		cout<<endl;
	}else{
		cout<<"输入的个数不合法"<<endl;
	}

	system("pause");
	return 0;
}

五、输出结果

  • 原始数据:DataType a[]={2,6,21,9,576,34,12,13,0};输入要排序的元素个数,观察输出结果:

由于是最大堆实现排序,所以输出结果呈现升序排列。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值