堆排序算法:
1、像合并排序算法一样,运行时间都为O(nlgn);
2、像插入排序算法一样, 都是原地排序算法,不需要开销多余的内存空间;
一、堆的介绍
首先,将我们需要排序的数列转化为一颗完全二叉树。树中的每一个节点与数组中的存放该节点值的那个元素对应。
假设:我们需要排序:int arr[] = {3, 2, 1, 9, 11, 4, 5}这个数列,则将它转化为二叉树,如图所示:
二叉树的类型有两种:
1、最大堆:除了树根以外的每个节点i,都有A[PARENT(i)] >= A[i],即某个节点的值至多和父类节点的值一样大;
2、最小堆:除了树根以外的每个节点i,都有A[PARENT(i)] <= A[i],即某个节点的值至少和父类节点的值一样小;
注:一般都用最大堆,也可以用最小堆, 这里后面的代码用的是最大堆的。
二、堆的排序
所谓堆的排序,就是将某一节点与它的子节点(左、右(如果有的话))按照最大堆的特点进行排序和替换。这里有一个很重要的前提条件:假设该节点的子节点(左、右)为根的两颗二叉树都是最大堆。
承接上面例子:
对index = 3, Value = 1的节点来说,进行排序, 该节点比它的左子节点和有右子节点都要小,则在三个节点中找到一个最大的节点替换index = 3, Value = 1的节点。
转换成:
三、创建最大堆
创建最大堆:将所有有子节点的节点进行堆的排序,从最大索引节点开始,到最小索引节点结束。 即从3开始, 到1结束。 这样就符合了堆排序的重要前提条件。
将上述数列进行创建最大堆后,如图所示:
四、堆排序算法
根据步骤三,创建了当前的最大的堆排序,其中arr[1]为该数列的最大数值。
然后将arr[1]与arr[length(arr)]替换。
再次对剩余的数值进行创建最大堆, index 从1 到 length(arr - 1),因为length(arr)已经最最大值了,没有必要将它加入进行排序了。
获取后的arr[1]为剩余数列的最大数值。 然后将arr[1]与arr[length(arr) - 1 ]进行替换。
这样以此类推,只到剩余最后一个数值, 在该数值为最小。
代码如下:
/*
* filename : heapsort.cpp
* author : Becky
* date : 2015 - 02 - 11
*/
/*include*/
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*define*/
void Exchage2Value(int *_leftValue, int *_rightValue)
{
int temp = *_leftValue;
*_leftValue = *_rightValue;
*_rightValue = temp;
}
int GetParentIndex(int _index)
{
return _index / 2;
}
int GetLeftIndex(int _index)
{
return _index * 2;
}
int GetRightIndex(int _index)
{
return _index * 2 + 1;
}
void Max_Heap(int *_pArr, int _index, int _heaplength)
{
int index = _index - 1;
int leftIndex = GetLeftIndex(_index) - 1;
int rightIndex = GetRightIndex(_index) - 1;
int maxIndex = 0;
int heaplength = _heaplength - 1;
if (leftIndex <= heaplength && rightIndex <= heaplength)
{
if (_pArr[index] >= _pArr[leftIndex] && _pArr[index] >= _pArr[rightIndex])
return;
if (_pArr[index] < _pArr[leftIndex] && _pArr[index] >= _pArr[rightIndex])
{
maxIndex = leftIndex;
Exchage2Value(_pArr + index, _pArr + leftIndex);
}
if (_pArr[index] < _pArr[rightIndex] && _pArr[index] >= _pArr[leftIndex])
{
maxIndex = rightIndex;
Exchage2Value(_pArr + index, _pArr + rightIndex);
}
if (_pArr[index] < _pArr[leftIndex] && _pArr[index] < _pArr[rightIndex])
{
maxIndex = _pArr[leftIndex] >= _pArr[rightIndex] ? leftIndex: rightIndex;
Exchage2Value(_pArr + index, _pArr + maxIndex);
}
}
else if (leftIndex <= heaplength)
{
if ( _pArr[index] >= _pArr[leftIndex] )
return;
if (_pArr[index] < _pArr[leftIndex])
{
maxIndex = leftIndex;
Exchage2Value(_pArr + index, _pArr + leftIndex);
}
}
else
return;
Max_Heap(_pArr, maxIndex + 1, _heaplength);
return ;
}
void Build_Max_Heap(int *_pArr, int _heaplength)
{
for (int i = _heaplength / 2 ; i != 0; i--)
{
Max_Heap(_pArr, i, _heaplength);
}
return;
}
void Heap_sort(int *_pArr, int _arrLength)
{
int arrLength = _arrLength;
int heapLength = _arrLength;
Build_Max_Heap(_pArr, heapLength);
for (int i = arrLength - 1; i != 0; i--)
{
Exchage2Value(_pArr + i, _pArr);
Build_Max_Heap(_pArr, --heapLength);
}
return;
}
int _tmain(int argc, _TCHAR* argv[])
{
int arr[] = {3, 2, 1, 9, 11, 4, 5, 3, 7, 8, 6, 10};
Heap_sort(arr, sizeof(arr) / 4);
for (int i = 0; i != sizeof(arr) / 4; i++)
{
printf("%d\t", arr[i]);
}
return 0;
}