while(true){
看书;
练习;
总结;
}
在学校的日子没啥事做,最近在学习算法导论,记录一下学习的过程。
堆排序是一种排序算法,其时间负责度是 o(n * lg n)
1.什么是堆?
堆可以被视为一颗完全二叉树,即除了最后一层可能不是满的,其余各层应该都是满的。如图:
一般情况下可以用一个数组表示
{16,14,10,8,7,9,3,2,4,1}
可以发现如下关系,假设某个节点为i则
PARENT(i) = i / 2 向下取整 //父节点坐标
LEFT(i) = 2i //左子节点坐标
RIGHT(i) = 2i+1 //右子节点坐标
最大堆的定义有两种,我们这里用最大堆,即堆中所有元素除了根节点外满足条件:
A[PARENT(i)] >= A[i] //当前节点小于父节点
能保证root根节点是堆中最大的节点。
1.保持堆的性质
伪代码如下:
MAX-HEAPIFY(A,i)//A表示存储该堆的数组,i表示以i为根的子树
l = LEFT(i); //获取i的左子节点,如果大于堆大小则返回null r = RIGHT(i); //获取i的右子节点,同上 if l !=null && A[l] > A[i] //查找i和i的左右子节点中最大的值 largest = l else largest = i end if r != null && A[r] > A[largest] largest = r end if largest != i //需要交换顺序 swap A[i] A[largest] MAX-HEAPIFY(A,largest) //递归调用,保证交换后依旧能维持最大堆的性质 end
用数组来举个栗子MAX-HEAPIFY(A,2)
{16, 4,10,14,7,9,3,2,8,1}
{16,14,10, 4,7,9,3,2,8,1}
{16,14,10, 8,7,9,3,2,4,1}
2.建堆
建堆只要对所有的非叶子节点循环调用MAX-HEAPIFY就可以保障最后生成的是一个最大堆
BUILD-MAX-HEAPIFY(A)
int heapSize = A.length //获得数组A(堆)的长度
cycleCount = heapSize / 2 //获得第一个有叶子节点的节点。 for cycleCount downTo 1{ MAX-HEAPIFY(A, cycleCount) }
3.堆排序算法
因为根节点始终是堆中最大的元素,所以我们每次将root元素取出和数组最后元素交换,并保障新的数组依旧为一个最大堆即可,伪代码如下
HEAP-SORT(A)
BUILD-MAX-HEAP(A) heapSize = A.length for i = A.length to 2 swap A[i] A[1] //将root与尾元素交换 heapSize = heapSize-1 //减少堆大小,此时数组的后面是已排序的 MAX-HEAPIFY(A,1) //因为将尾元素换到了root处,所以要从新保持最大堆的性质