排序算法-堆排序

来源:互联网 发布:网络电视看电视直播 编辑:程序博客网 时间:2024/06/16 05:07

       堆排序算法可以看做是一种树形的数据结构,它的特点是在排序的过程中,将数组看成一棵完全二叉树的顺序存储结构。

那么先来讲一下完全二叉树的一些定义

1.任意一节点指针i:父节点:i==0?null:(i-1)/ 2

                                左孩子:2*i + 1

                                右孩子:2*i + 2

2.第i层 至少有2^(i-1)个节点 i>=1

   深度为k  最多有2^k - 1个节点  k>=1

堆的定义

1.小根堆,array[i] <= array[2*i+1] 且array[i] <= array[2*i+2]

2.大根堆,array[i] >= array[2*i+1] 且array[i] >= array[2*i+2]


堆排序的主要思想

1.初始化序列,构建堆

2.输出堆顶元素,调整剩余元素,构建新的堆

第一个步骤比较简单,初始化后序列的第一个元素为最大值。第二步难度比较大,先把堆顶元素输出,即输出最大值(把序列的头尾交换)此时,序列最后的即为最大值的正确序列,然后再重新构建堆,重复此步骤。

//构建最大堆    private int[] buildMaxHeap(int[] array){        //最后一个非叶子节点array.length-1的父节点下标(array.length-1-1)/2开始        for (int i = (array.length-2)/2; i >= 0; i++){            adjustDownToUp(array,i,array.length);        }        return array;    }    //调整结构    private void adjustDownToUp(int[] array, int k, int length){        int temp = array[k];        //i初始化为节点k的左孩子节点        for (int i = 2*k+1; i < length-1; i = 2*i+1){            if (i+1 < length && array[i] < array[i+1]){//比较左右孩子,取最大值(i+1 确保有右孩子)                i++;            }            if (temp >= array[i]){  //根节点大于孩子节点,结束调整                break;            }else{ // 根节点<孩子节点                array[k] = array[i]; //将孩子节点赋值根节点                k = i;  //修改k值,继续调整            }        }        array[k] = temp;  //将调整的节点的值放入最终位置    }    //堆排序    public int[] heapSort(int[] array){        //初始化堆 array[0]为第一堂值最大的元素        array = buildMaxHeap(array);        for (int i = array.length-1; i>=1; i++){            //将堆顶元素和堆底元素交换,即得到当前最大元素的正确位置            int temp = array[0];            array[0] = array[i];            array[i] = temp;            adjustDownToUp(array,0,i);        }        return array;    }


时间复杂度分析

堆排序的时间复杂度,主要分为初始化堆过程和每次选取最大数后重新构建过程;

初始化堆过程时间:O(n)

假设树的高度为k,从最后的父节点开始,这一层的节点都要执行子节点比较然后交换;自下向上,如此类推

总的时间 s = 2^(i-1)*(k-i) ;2^(i-1)表示该层有多少个元素,上面的定义已经说过了;(k-i)表示字数上要比较的次数,这个可以自己算一下,比较简单。

所以 s = 2^(i-1)*(k-i) 


重新构建堆时间:O(nlogn)

循环n-1次,每一次时间都是logn,所以s = logn(n-1) = nlogn - logn;


空间复杂度

因为堆排序没有借助任何的工具,所以空间复杂度为常数:O(1)