zoukankan      html  css  js  c++  java
  • 算法-堆与堆排序

    堆:
    需满足两个条件:
    1、是一个完全二叉树
    2、parent > child (大顶堆)

    完全二叉树,确保可以用数组来表示,并且从任意节点开始出发,可以轻松得到其父节点和两个子节点。
    对于节点i,parent = (i - 1) / 2, c1 = i * 2 + 1, c2 = i * 2 + 2

    heapify:
    可以把一个完全平方树看成很多个子树,每个子树就3个元素,对这个子树按照parent>child的规则进行调整,调整后,再递归的对其子节点进行判断。这个过程称为heapify。

    代码如下:

    public void heapify(int[] tree, int n, int i) {
        int max = i;
        int c1 = i * 2 + 1;
        int c2 = i * 2 + 2;
    
        if (c1 < n && tree[c1] > tree[max])
            max = c1;
        if (c2 < n && tree[c2] > tree[max])
            max = c2;
    
        if (max != i) {
            swap(tree, max, i);
            heapify(tree, n, max);
        }
    }
    

    构建堆:
    将一个数组构造成一个堆,只需要从最后一个节点的父节点开始,往前遍历,对每个节点进行heapify。最后这个数组就是一个堆。

    代码如下:

    public void buildHeap(int[] tree, int n) {
        int lastNode = n - 1;
        int parent = (lastNode - 1) / 2;
    
        for (int i = parent; i >= 0; --i) {
            heapify(tree, n, i);
        }
    }
    

    堆排序:
    利用堆的性质,来进行排序。

    由上图可以看出整个过程就是将最大元素(第一个元素)与最后一个元素进行交换,然后将剩下的n-1个元素进行 heapify 操作,再将最大元素与倒数第二个元素进行交换。。。

    代码如下:

    public void heapSort(int[] tree) {
        buildHeap(tree, tree.length);
    
        for (int i = tree.length - 1; i >= 0; --i) {
            swap(tree, 0, i);
            heapify(tree, i, 0);
        }
    }
    

    堆排序完整代码:

    public class HeapSort{
    
        public static void swap(int[] arr, int a, int b) {
            int t = arr[a];
            arr[a] = arr[b];
            arr[b] = t;
        }
    
        public void heapify(int[] tree, int n, int i) {
            int max = i;
            int c1 = i * 2 + 1;
            int c2 = i * 2 + 2;
    
            if (c1 < n && tree[c1] > tree[max])
                max = c1;
            if (c2 < n && tree[c2] > tree[max])
                max = c2;
    
            if (max != i) {
                swap(tree, max, i);
                heapify(tree, n, max);
            }
        }
    
        public void buildHeap(int[] tree, int n) {
            int lastNode = n - 1;
            int parent = (lastNode - 1) / 2;
    
            for (int i = parent; i >= 0; --i) {
                heapify(tree, n, i);
            }
        }
    
        public void heapSort(int[] tree) {
            buildHeap(tree, tree.length);
    
            for (int i = tree.length - 1; i >= 0; --i) {
                swap(tree, 0, i);
                heapify(tree, i, 0);
            }
        }
    
    
        public static void main(String[] args) {
            int[] arr = {1, 4, 9, 3, 5, 2, 7, 0, 6, 8};
            
            HeapSort sort = new HeapSort();
            sort.heapSort(arr);
            System.out.println(Arrays.toString(arr));
        }
    }
    

    参考:

  • 相关阅读:
    Maven与Eclipse整合使用
    Maven学习总结(五)——聚合与继承【如果想一次构建多个项目模块,那我们就需要对多个项目模块进行聚合】
    Maven的核心概念:maven仅仅定义了抽象的生命周期,具体的任务都是交由插件完成的
    使用Maven构建项目---【重点需要掌握:Jetty和Maven两种项目骨架】
    Maven项目构建过程练习
    maven编码gbk的不可映射字符”解决办法
    Maven
    Spring Aop的方法执行简单模型
    2016年看过的书
    ExcelReader
  • 原文地址:https://www.cnblogs.com/cloudflow/p/13894351.html
Copyright © 2011-2022 走看看