排序算法:堆排序
标签(空格分隔): 选择排序、堆排序
一、堆的特点(分为最大堆和最小堆,这里以最大堆说明)
- 每个节点最多可以有两个节点
- 根节点的键值是所有堆节点键值最大者,且每个节点的值都比其孩子节点大
- 除了根节点没有兄弟节点,最后一个左子节点可以没有兄弟节点,其他节点必须要有兄弟节点
二、堆排序
- 堆排序(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};输入要排序的元素个数,观察输出结果:
由于是最大堆实现排序,所以输出结果呈现升序排列。