堆排序
大约 3 分钟
堆排序
堆排序(Heap Sort)
堆排序是指利用堆这种数据结构所设计的一种排序算法。 堆积是一个近似完全二叉树的结构,并同时满足堆积的性质; 即子结点的键值或索引总是小于(或者大于)它的父节点。
算法描述
- 将初始等排序关键字序列(R1,R2...Rn)构建成大顶堆,此堆为初始的无序区;
- 将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2...Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n];
- 由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2...Rn-2)和新的有序区(Rn-1,Rn)。 不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。
个人理解
先建立一个最小堆,则最小值入堆顶。父结点比左节点小,左节点比右节点小。 将堆顶放到堆尾。
动图演示
代码实现
//因为是数组,下标从0开始,所以,下标为n根结点的左子结点为2n+1,右子结点为2n+2;
//初始化值,建立初始堆
$arr=array(49,38,65,97,76,13,27,50);
$arrSize=count($arr);
//将第一次排序抽出来,因为最后一次排序不需要再交换值了。
buildHeap($arr,$arrSize);
for($i=$arrSize-1;$i>0;$i--){
swap($arr,$i,0);
$arrSize--;
buildHeap($arr,$arrSize);
}
//用数组建立最小堆
function buildHeap(&$arr,$arrSize){
//计算出最开始的下标$index,如图,为数字"97"所在位置,比较每一个子树的父结点和子结点,将最小值存入父结点中
//从$index处对一个树进行循环比较,形成最小堆
for($index=intval($arrSize/2)-1; $index>=0; $index--){
//如果有左节点,将其下标存进最小值$min
if($index*2+1<$arrSize){
$min=$index*2+1;
//如果有右子结点,比较左右结点的大小,如果右子结点更小,将其结点的下标记录进最小值$min
if($index*2+2<$arrSize){
if($arr[$index*2+2]<$arr[$min]){
$min=$index*2+2;
}
}
//将子结点中较小的和父结点比较,若子结点较小,与父结点交换位置,同时更新较小
if($arr[$min]<$arr[$index]){
swap($arr,$min,$index);
}
}
}
}
//此函数用来交换下数组$arr中下标为$one和$another的数据
function swap(&$arr,$one,$another){
$tmp=$arr[$one];
$arr[$one]=$arr[$another];
$arr[$another]=$tmp;
}
var_dump($arr);
$arr = [20, 40, 60, 80, 30, 70, 90, 10, 50, 0, 5];
/**
* @param $arr
* 堆排序
*/
function heapSort(&$arr)
{
$arrSize = count($arr); // 取数据长度
// 建最小堆,依次入堆尾
for ($i = $arrSize - 1; $i > 0; $i--) {
buildMinHeap($arr, $arrSize); // 建最小堆
$arrSize--;
swap($arr, $i, 0); // 入堆尾
}
}
/**
* @param $arr
* @param $arrSize
* 最小堆
*/
function buildMinHeap(&$arr, $arrSize)
{
$index = floor($arrSize / 2) - 1; // 顶点(最尾)
for (; $index >= 0; $index--) {
$left = $index * 2 + 1; // 左节点
$right = $index * 2 + 2; // 右节点
if ($left < $arrSize) $min = $left; // 左节点入哨兵
if ($right < $arrSize && $arr[$right] < $arr[$min]) $min = $right; // 右节点入哨兵
if ($arr[$min] < $arr[$index]) swap($arr, $min, $index); // 将小值入顶点
}
}
/**
* @param $arr
* @param $min
* @param $index
* 数据交换
*/
function swap(&$arr, $min, $index)
{
$tmp = $arr[$min];
$arr[$min] = $arr[$index];
$arr[$index] = $tmp;
}
heapSort($arr);
var_dump($arr);