堆排序
Posted duanjiapingjy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆排序相关的知识,希望对你有一定的参考价值。
不稳定 O(nlogn)
大顶堆(从大到小排序):每个结点的值都大于等于其左右孩子的值的二叉树
小顶堆(从小到大排序):每个结点的值都小于等于其左右孩子的值的二叉树
如何排序?
将待排序序列构建成一个小顶堆,堆顶的元素即为所有元素中的最小值
在输出堆顶的最小值之后,调整堆,使剩余的n-1个元素又建成一个小顶堆,此时的堆顶元素为次小元素
以此类推,直到堆为空
如何在输出堆顶元素之后调整堆?
(1)以堆中的最后一个元素代替堆顶元素,此时堆顶元素的左右子树均符合小顶堆或者大顶堆,只需从上到下调整即可
(2)比较对顶元素和其左右孩子,
如果右孩子的值最小,则,将右孩子和堆顶元素交换,此时,可能导致堆顶元素的右子树不满足条件,以相同方法调整右子树
如果左孩子的值最小,则,将左孩子和堆顶元素交换,此时,可能导致堆顶元素的左子树不满足条件,以相同方法调整左子树
如果堆顶元素就是最小的,不用调整。
如何将待排序序列构建成一个堆?
将待排序序列看成一个完全二叉树,有n个元素,标号从1开始,则最后一个标号就是n,最后一个元素即为完全二叉树的最后一个叶子节点,最后一个叶子节点的父节点即为最后一个非叶子节点。编号为n的节点的父结点的编号为n/2向下取整,从最后一个非叶子节点开始,像上述调整过程一样,从下到上调整完全二叉树为小顶堆或者大顶堆。
public static void heapSort(int[] array){ //1.根据待排序序列构建一个小顶堆 createHeap(array); System.out.println("建立小顶堆完成"); //2.输出堆顶元素,然后调整堆 //输出堆顶元素,用最后一个元素替换堆顶元素,然后调整堆为小顶堆,循环上述过程,直到最后一个元素 for(int i=0;i<array.length;i++){ System.out.print(array[0]+" "); array[0] = array[array.length-1-i]; //用最后一个元素代替堆顶元素之后,可能只会导致堆顶和它的左右孩子不满足要求,调整堆顶即可 judgeHeap(array, 0, array.length-i-1); } } public static void createHeap(int[] array){ int length = array.length; //从第n/2向下取整个元素开始调整,第n/2向下取整个元素在数组中的下标为n/2向下取整-1 for(int i=length/2-1;i>=0;i--){ judgeHeap(array, i, length); } } public static void judgeHeap(int array[],int k,int length){ //根据完全二叉树的定义,一个节点i如果有左孩子,左孩子的编号为2*i,右孩子为2*i+1 //左孩子在数组中的下标为2(i+1)-1=2*i+1 右孩子在数组中的下标为2(i+1)+1-1=2*(i+1) //每次调整的时候,都要从当前节点一直调整到当前节点下的叶子节点 for(int i=k;i<length;){ if(2*i+1>=length){//表示当前节点就是叶子节点 break; } int root = array[i]; int leftChild = Integer.MAX_VALUE; int rightChild = Integer.MAX_VALUE; //判断是否有左孩子 if(2*i+1 < length){ leftChild = array[2*i+1]; } if(2*(i+1) < length){ rightChild = array[2*(i+1)]; } int index = 0;//记录当前节点和它的左右孩子中最小的那个数的下标 if(leftChild<=rightChild){ index = 2*i+1; }else{ index = 2*(i+1); } if(root<array[index]){ index = i; } //System.out.println("要替换的下标:"+index+"--"+i); if(index != i){//一个节点跟它的左右孩子节点中,最小的不是根节点,交换 int temp = array[index]; array[index] = array[i]; array[i] = temp; //交换之后,可能会导致被交换的那个节点组成的子树不满足小顶堆,因此,要再调整 i = index; }else{ //如果没有交换,则不会打乱小顶堆,什么也不做,直接调整下一个节点 break; } //listArray(array); } } 原始数据:49 38 65 97 76 13 27 49 要替换的下标:7--3 49 38 65 49 76 13 27 97 要替换的下标:5--2 49 38 13 49 76 65 27 97 要替换的下标:1--1 要替换的下标:2--0 13 38 49 49 76 65 27 97 要替换的下标:6--2 13 38 27 49 76 65 49 97 建立小顶堆完成 要替换的下标:2--0 27 38 97 49 76 65 49 97 要替换的下标:6--2 27 38 49 49 76 65 97 97 要替换的下标:1--0 38 97 49 49 76 65 97 97 要替换的下标:3--1 38 49 49 97 76 65 97 97 要替换的下标:1--0 49 65 49 97 76 65 97 97 要替换的下标:1--1 要替换的下标:2--0 49 65 76 97 76 65 97 97 要替换的下标:1--0 65 97 76 97 76 65 97 97 要替换的下标:0--0
以上是关于堆排序的主要内容,如果未能解决你的问题,请参考以下文章