堆排序
堆的一个重要应用,堆排序,主要是将将一组数据排成有序的序列,如何实现?先将这组数据放到二叉树中建大堆,然后再把第一个数据与最后一个交换,最大的数据就在最后,然户把其余n-1个数据继续调成成大堆,再把第一个和次大的交换,每次排序后,无序的数据范围缩小1,直到最后这个无序的序列只剩最后一个数据,就会完成排序
分两步:
一:建大堆(升序)
//向下调整建大堆
void _AjustDown(int* heap, size_t root, size_t n)
{
assert(n>0);
int parent = root;
int child = parent * 2 + 1;
while (child < n)
{
//选较大的孩子
if (child + 1<n && heap[child + 1] > heap[child])
{
child++;
}
//比较父亲节点与孩子节点的大小
if (heap[child] >heap[parent])
{
swap(heap[child], heap[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
二:排序
void HeapSort(int*a, size_t n)
{
assert(a);
//建大堆
for (int i = (n - 2) / 2; i >= 0; --i)
{
_AjustDown(a, i,n );//向下调整
}
//排序原理是选择排序第一个与最后一个交换,再讲第一个与次大交换,直到最后一个
int end = n - 1;
while (end)
{
swap(a[0], a[end]);//第一个与最后一个交换
_AjustDown(a, 0, end);//调整成堆;
--end;//第一个与次大的交换直到第一个
}
}
其余n-1个元素继续调整为大堆,然后再排序,直到最后一个元素,此时就成为一个有序序列
完整代码
#pragma once
#include<iostream>
using namespace std;
void _AjustDown(int* heap, size_t root, size_t n)
{
assert(n>0);
int parent = root;
int child = parent * 2 + 1;
while (child < n)
{
//选较大的孩子
if (child + 1<n && heap[child + 1] > heap[child])
{
child++;
}
//比较父亲节点与孩子节点的大小
if (heap[child] >heap[parent])
{
swap(heap[child], heap[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void HeapSort(int*a, size_t n)
{
assert(a);
//建大堆
for (int i = (n - 2) / 2; i >= 0; --i)
{
_AjustDown(a, i,n );//向下调整
}
//排序原理是选择排序第一个与最后一个交换
int end = n - 1;
while (end)
{
swap(a[0], a[end]);//第一个与最后一个交换
_AjustDown(a, 0, end);//调整成堆;
--end;//第一个与次大的交换直到第一个
}
}
void TestHeapSort()
{
int a[] = { 5, 6, 3, 2, 1, 4 };
int len = sizeof(a) / sizeof(a[0]);
HeapSort(a, len);
}
时间复杂度为O(N*logN)