Java 堆排序

来源:互联网 发布:mac桌面文件夹隐藏 编辑:程序博客网 时间:2024/06/07 08:00

堆排序,我想了好几天,最后还是参考了一下别人的博客,看了许多的解释,不过还是下面这些最好理解:

http://www.ixywy.com/zsjz/2564.html (这篇的不是博客)

http://blog.csdn.net/zdp072/article/details/44227317 (csdn博客)

好了,代码如下:

package com.vgbh;/* * 堆排序 */public class heapSorting {    /*    堆排序算法思想:    堆排序,顾名思义,就是基于堆。    因此先来介绍一下堆的概念:    堆分为最大堆和最小堆,其实就是:完全二叉树或近似完全二叉树。    二叉树的特点:    1.最大堆要求节点的元素都要大于其孩子。    2.最小堆要求节点元素都小于其左右孩子。    有了上面的定义,我们可以得知,处于最大堆的根节点的元素一定是这个堆中的最大值。    其实我们的堆排序算法就是抓住了堆的这一特点,每次都取堆顶的元素,将其放在序列最后面,然后将剩余的元素重新调整为最大堆,依次类推,最终得到排序的序列。    本质上讲,堆排序是一种选择排序,每次都选择堆中最大的元素进行排序。只不过堆排序选择元素的方法更为先进,时间复杂度更低,效率更高。     */    /*    步骤:    1 首先从第一个非叶子节点开始,比较当前节点和其孩子节点,将最大的元素放在当前节点,交换当前节点和最大节点元素。    2 将当前元素前面所有的元素都进行1的过程,这样就生成了最大堆    3 将堆顶元素和最后一个元素交换,列表长度减1。由此无序区减1,有序区加1    4 剩余元素重新调整建堆    5 继续3和4,直到所有元素都完成排序    */    /*    时间复杂度:    堆排序的平均时间复杂度为O(nlogn),接近于最坏的时间复杂度。    在最好情况下,时间复杂度为O(1).     */    /*    算法总结:    堆排序时间复杂度:O(nlogn)    堆排序对原始记录的排序状态并不敏感,其在性能上要远远好过于冒泡、简单选择、直接插入排序。     */    private static int n = 10 ;//数组长度    private static int[] arr = new int[n] ;//数组    static PublicOut pc = null ;//定义外部对象    public static int count = 0;//运行次数    public static void main(String[] args) {        pc = new PublicOut();        pc.data(arr, n);        pc.prin(arr, n);        heapSorting hs = new heapSorting();        hs.heap(arr);        pc.prin(arr, n);        //System.out.println("最后共运行" + count + "次。");    }    //数据结构的p281有详细的运算过程     详解:http://www.ixywy.com/zsjz/2564.html    //堆排序    public void heap (int[] arr) {        //将数组转化为大堆        for (int i=arr.length / 2; i>=0; i--) {            buildHeap(arr,i,arr.length);        }        //将最小值与最大值交换,并调整二叉树        for (int i=arr.length - 1; i>0; i--) {            swap(arr, 0, i);//将父元素和当前未经排序子序列的最后一个记录交换            buildHeap(arr, 0, i);//交换之后,重新比对二叉树,不符合则要调整。        }    }    /*     * 创建堆     * arr:数组     * x:需要构建堆的根节点的序号     * y:数组长度     */    public void buildHeap (int[] arr,int x,int y) {        count++;        int child ;        int father ;        for (father = arr[x]; leftChild(x) < y; x = child) {            child = leftChild(x);            //如果左子树小于右子树,则需要比较右子树和父节点            if (child != y-1 && arr[child] < arr[child+1]) {                child++;//自增可以指向父节点            }            //如果父节点小于孩子节点,则需要交换            if (father < arr[child]) {                arr[x] = arr[child];            } else {                break;//大堆未被破坏,不需要调整            }        }        arr[x] = father;    }    //交换元素    public void swap (int[] arr,int x,int y) {        int tmp = arr[x];        arr[x] = arr[y];        arr[y] = tmp;    }    //获取左孩子结点    public int leftChild (int i) {        return 2 * i + 1;    }}

如果关于堆排序还有不会的,可以发邮件到我的邮箱。

原创粉丝点击