堆排序

堆的定义
n个关键字序列Kl,K2,…,Kn称为(Heap),当且仅当该序列满足如下性质(简称为堆性质):
ki<=k(2i)且ki<=k(2i+1)(1≤i≤ n),当然,这是小根堆,大根堆则换成>=号。k(i)相当于二叉树的非叶子结点,K(2i)则是左子节点,k(2i+1)是右子节点
若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:
树中任一非叶子结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。


堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,可以利用数组的特点快速定位指定索引的元素。
堆排序是一种不稳定的排序方法,平均性能O(N*logN)。
由于创建堆的时候需要比较多的比较次数,所以堆排序不适合记录较少的排序。


完全二叉树的父节点、子节点算法
节点i的父节点为不大于(i/2)的最大整数
节点i的左子节点的编号为2i + 1

节点i的右子节点的编号为2(i+1)


// 堆排序主函数
function heapSort(&$arr)
{
	initHeap($arr, 0, count($arr) - 1);

	for($end = count($arr) - 1; $end > 0; --$end)
	{
		$temp = $arr['0'];
		$arr['0'] = $arr[$end];
		$arr[$end] = $temp;
		ajustNodes($arr, 0, $end - 1);
	}
}

// 初始化堆:根据堆的特性,建立一个堆
function initHeap(&$arr)
{
	$len = count($arr);
	for ($start = floor(($len - 1) / 2); $start >= 0; --$start)
	{
		ajustNodes(&$arr, $start, $len - 1);
	}

	return $arr;
}

// 调整节点:比较节点与它的子节点的大小,调换节点位置
function ajustNodes(&$arr, $start, $end)
{
	$leftChild = $start * 2 + 1;
	$rightChild = ($start + 1) * 2;

	$maxInx = $start;
	if ($leftChild <= $end)
	{
		if ($arr[$maxInx] < $arr[$leftChild])
		{
			$maxInx = $leftChild;
		}

		if ($rightChild <= $end && $arr[$maxInx] < $arr[$rightChild])
		{
			$maxInx = $rightChild;
		}

		if ($start != $maxInx)
		{
			$temp = $arr[$start];
			$arr[$start] = $arr[$maxInx];
			$arr[$maxInx] = $temp;

			if ($end >= (2 * $maxInx + 1))
			{
				ajustNodes($arr, $maxInx, $end);
			}
		}
	}
}


$arr = array(3,9,6,8,2,5,4,7,1);

heapSort($arr);

print_r($arr);


你可能感兴趣的:(堆排序)