自己整理的算法 (6)堆排序

package sort;

//最大堆的特性是,某个节点的值最多和其父节点的值一样大。这样,堆中的最大元素存放在根节点中
//;并且,在以某一个节点为根的子树中,各节点的值都不大于该子树根节点的值

public class HeapSort {  

    public static void heapSort(int[] list) {
        if (list == null || list.length <= 1) {
            return;
        }
      //构建最大堆
        //相当于add的作用,此方法结束后,就构建好了有序的二叉堆
        buildMaxHeap(list);
     //循环,每次把根节点和最后一个节点调换位置
        for (int i = list.length - 1; i >= 1; i--) {
        	 int tmp = list[0];
             list[0] = list[i];
             list[i] = tmp;
     //每次堆得长度都减少1,也就是排除置换到最后的根节点
             //相当于删除最大节点(其实是放在数组最后,然后再排序忽视最后的那些位置)
             //把最后的节点放在根节点处,然后在用maxHeap进行比较交换即可
             //此时从index=0即交换后的根节点位置开始重新排序
            maxHeap(list, 0, i);
        }
    }
    //根据输入数组构建一个最大堆
    private static void buildMaxHeap(int[] list) {
        if (list == null || list.length <= 1) {
            return;
        }
        //这个half为可能存在子节点的最大的位置
        for (int i = list.length/2; i >= 0; i--) {
            maxHeap(list, i, list.length);
        }
    }
    //堆调整,使其生成最大堆
    private static void maxHeap(int[] list, int index, int heapSize) {
       // 左子节点索引
    	int left = index * 2 + 1;
      //右子节点索引
        int right = index * 2 + 2;
      //最大节点索引
        int largest = index; 

        //如果左子节点大于父节点,则将左子节点作为最大节点
        if (left < heapSize && list[left] > list[index]) {
            largest = left;
        }
        //如果右子节点比最大节点还大,则最大节点为右子节点
        if (right < heapSize &&list[right] > list[largest]) {
            largest = right;
        }
        //最后,如果最大节点和父节点不一致,则交换他们的值
        if (index != largest) {
        	 int tmp = list[index];
             list[index] = list[largest];
             list[largest] = tmp;
         //交换完父节点和子节点的值,对换了值的子节点检查是否符合最大堆特性

            maxHeap(list, largest, heapSize);
        }
    }  

    public static void main(String[] args) {
        int[] list = { 4,9,8,2,-1,5 };
        heapSort(list);
        for(int i =0;i<list.length;i++)
        	System.out.print(list[i]+" ");
    }
}

  

时间: 2024-10-18 18:13:38

自己整理的算法 (6)堆排序的相关文章

排序算法系列——堆排序

记录学习点滴,菜鸟成长记 堆排序引入了另一种算法设计技巧:使用一种我们称之为“堆”的数据结构来进行数据管理. 堆排序算是真正意义上的利用数据结构来求解数组排序的方法. “插入排序”和“归并排序”可以看做是一种“计算机体力活”,体现的思想更多的是去模拟最简单的人类思维,比如插入排序过程中的比较,归并中子问题合并时的比较. “堆排序”可以看做是“计算机脑力活”,他利用了一种结构化的语言来表达,这种结构化带来一些性质,比如左右孩子.比[堆大小的一半向下取整]大的下标都是叶节点不需要维护其最大堆性质等.

【数据结构与算法】堆排序

堆排序的时间复杂度是O(nlogn),下面上代码 public class HeapSort { public void adjustHeap(int[] in, int index, int length) { int leftcIndex = index * 2 + 1; int rightcIndex = index * 2 + 2; int bigest = index; while (leftcIndex < length || rightcIndex < length) { if

常用算法之----堆排序

预备知识 堆排序 堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序.首先简单了解下堆结构. 堆 堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆:或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆.如下图: 同时,我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子 该数组从逻辑上讲就是一个堆结构,我们用简单的公式来描述一下堆的定义就是: 大顶

【算法】堆排序

堆排序 上一篇博客讲了堆这种数据结构,它提供了一种接口getMax接口,好消息是获得最大值的时间复杂度仅仅为O(lgn),因此联想到之前的选择排序算法, 每次从剩下的未排序元素中找到极值元素,将其放入对应的位置. 由于一般的选择排序在寻找最大值时需要遍历数组,遍历数组的复杂度为O(n),因此造成了时间的浪费,如若将待排序的数组进行一系列整理,例如将其整理成有特点的堆这种数据结构.那么我们有理由相信,能将选择排序的时间复杂度降低到O(nlgn) 堆排序算法 具体的堆排序算法如下,很容易理解 HEA

排序算法之堆排序(优先队列)

1.堆排序的堆,其实是一个 完全二叉树.既是一个结点要么是叶子结点,要么必定有左右两个子节点的树. 2.堆有序:每个结点的值,都必须大于两个子节点.但是两个子结点的大小不作要求. 3.一棵大小为N的完全二叉树,高度为lgN(层). 用数组实现堆,假设数组下标从0开始,下标为k的元素,它的左子树是2k+1,右子树是左子树+1,即2k+2 一:由上至下的有序化(下沉) 如果堆的有序状态,因为某个结点比它的两个子结点或者其中之一小而打破了,那么可以通过与两个子结点中的较大者来交换. 交换后可能会在子结

【算法设计-堆排序】大根堆排序

1.堆排序不仅拥有与归并排序一样的时间复杂度为o(nlgn),而且空间复杂度所占秩序额外的几个元素空间,这个又有插入排序的优势. 2.堆排序分为3部分,第一部分是保持堆的性质的函数MAX_HEAPIFY函数,用于保持堆的性质:父结点的值要大于子节点. 第二部分是创建大根堆的函数,BUILD_MAX_HEAP这个函数从第一个非叶节点开始进行MAX_HEAPIFY函数.最终创建一个大根堆. 第三部分是堆排序部分,输出一个最大值KEY[1],然后将最后一个值替换第一个值,重复进行. 代码如下: #in

必须知道的八大种排序算法【java实现】(三) 归并排序算法、堆排序算法详解

一.归并排序算法 基本思想: 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序序列. 归并排序示例: 合并方法: 设r[i-n]由两个有序子表r[i-m]和r[m+1-n]组成,两个子表长度分别为n-i +1.n-m. j=m+1:k=i:i=i; //置两个子表的起始下标及辅助数组的起始下标 若i>m 或j>n,转⑷ //其中一个子表已合并完,比较选取结束 //选取r[i]和r[j]

【转】算法之堆排序

http://blog.csdn.net/SJF0115/article/details/8610201 前序: (二叉)堆数据结构是一种数组对象,它可以被视为一棵完全二叉树.树中每个节点与数组中存放该节点值的那个元素对应. 树的每一层都是填满的,最后一层除外. 树的根为a[1] (在这里是从1开始的,也可以从0开始),给定了某个节点的下标i,其父节点为i/2,左二子为2*i,右儿子为2*i+1. 二叉堆满足二个特性: 1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值. 2.每个

排序算法之堆排序(Heapsort)解析

一.堆排序的优缺点(pros and cons) (还是简单的说说这个,毕竟没有必要浪费时间去理解一个糟糕的的算法) 优点: 堆排序的效率与快排.归并相同,都达到了基于比较的排序算法效率的峰值(时间复杂度为O(nlogn)) 除了高效之外,最大的亮点就是只需要O(1)的辅助空间了,既最高效率又最节省空间,只此一家了 堆排序效率相对稳定,不像快排在最坏情况下时间复杂度会变成O(n^2)),所以无论待排序序列是否有序,堆排序的效率都是O(nlogn)不变(注意这里的稳定特指平均时间复杂度=最坏时间复