还记得之前说的选择排序么?忘记了看这里<选择排序>。 选择排序i时,我们需要从n-i+1个序列中选择一个最小的数字, 那么势必就要比较多次来寻找到最小的那一个元素从而来进行排序,这种排序虽然相对于冒泡排序有效的减少了交换所带来的开销,但是多次比较对于比较的结果却没有进行记录,当排序第1个数字的时候需要从第1.....n中找到最小的数字进行和第1个进行比较交换,当我们需要排序第2个数字时,同样需要将上一步比较过的过程重新进行一次。这样的操作并没有把每一趟的比较结果保存下来,在后一趟的比较中,有许多比较在前一趟已经做过了,但由于前一趟排序时未保存这些比较结果,所以后一趟排序时又重复执行了这些比较操作,因而记录的比较次数较多。Floyd和Williams在1964年共同发明发明了堆这样的数据结构,同时提出了堆排序的概念,堆排序其实是选择排序的一个升级版本,是在每一次选择最小的记录的同时对其他的元素也相应的进行调整。 从而有效的减少了比较的次数而带来的价值就是运算效率的大幅度提升。要讲堆排序需要先讲解堆这种数据结构。
堆是具有下列性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。其实对就是一种完全二叉树,只是节点元素的关系满足根节点比孩子节点都大或者小,所以不难看出一个堆的最值在root根节点,堆结构中的每一个子树也都是一个堆结构。对堆结构的二叉树按照按层顺序标号,root节点为1则有如下关系:
大堆: P[i] >= P[2*i] && P[i] >= P[2*i+1] 小堆:P[i] <= P[2*i