zoukankan      html  css  js  c++  java
  • 排序之堆排序

    在本例中实现了堆数据结构,sort()方法排序堆实例。

    import java.util.Comparator;
    import java.util.Iterator;
    import java.util.function.Consumer;
    
    /**
     * 二叉堆
     * 成员变量:数组 arr、元素数量 count、
     * 成员方法:是否空 isEmpty 、大小 size、插入 insert、删除最大值并返回 deleteMax、
     *             比较less、交换exch、下沉sink、上浮swim
     */
    public class Heap <Key extends Comparable<Key>> implements Iterable<Key>{
        private Key[] arr; //堆内部维护的数组
        private int count; //数组内部的元素
    
        public Heap(Key[] array){
            count = array.length;
            arr = (Key[])new Comparable[count+1];
            for(int i=1;i<=array.length;i++){
                arr[i] = array[i-1];
            }
        }
    
        public void resize(int size){
            Key[] temp = (Key[])new Comparator[size];
            for(int i=1;i<=count;i++){
                temp[i]=arr[i];
            }
            arr = temp;
        }
    
        public boolean isEmpty() {
            if(count==0)return true;
            return false;
        }
        public int size(){
            return count;
        }
    
        public void insert(Key key){
            if(count+1>=arr.length){
                resize(count*2);
            }
            arr[count+1] = key;
            count++;
            swim(count);
        }
    
        public Key deleteMax(){
            if(isEmpty()) return null;
            Key temp = arr[1];
            exch(1,count);
            arr[count--]=null;
            sink(1,count);
            return temp;
        }
        public boolean less(int a,int b){
            if(arr[a].compareTo(arr[b])<0) return true;
            return false;
        }
    
        public void exch(int a,int b){
            Key temp = arr[a];
            arr[a] = arr[b];
            arr[b] = temp;
        }
        // sink() swim() 方法是堆数组的关键
        public void sink(int k, int n){
            while (2*k<=n){//有子节点
                int j=2*k;
                if(j+1<=n && less(j,j+1)) j++;
                if(less(j,k)) break;
                exch(j,k);
                k=j;
            }
        }
    
        public void swim(int k){
            int j=k/2;
            while (j>=1){//有父节点
                if(less(j,k)){
                    exch(j,k);
                    k=j;
                }
            }
        }
    
        public void sort(){
            //初始化数组
            //从倒数的二排开始使用sink()方法逐渐是整个堆有序化
            for(int i = count/2; i>=1; i--){
                sink(i,count);
            }
            System.out.println("初始化结束");
            //排序
            int N = count;
            while(N>1){
                exch(1,N--);
                sink(1,N);  //注意! 此处sink()方法的第二个参数为N; 因为需要sink()方法排序堆的大小为N
            }
            System.out.println("排序结束");
        }
    
        //迭代器
        @Override
        public Iterator<Key> iterator() {
            return new Iterator<Key>() {
                int i = 1;
                @Override
                public boolean hasNext() {
                    if(i<=count)return true;
                    return false;
                }
    
                @Override
                public Key next() {
                    return arr[i++];
                }
            };
        }
    }
    /**
     * 测试案例
     */
    public class TestCase {
        public static void main(String[] args) {
            Integer[] a = new Integer[]{1,6,34,2,5,3,4,45,6,22};
            Heap<Integer> integerHeap = new Heap<>(a);
            System.out.println("start sort");
            integerHeap.sort();
            System.out.println("sorted");
            for(Integer e : integerHeap){
                System.out.println(e);
            }
        }
    }
    
    //结果
    start sort
    初始化结束
    排序结束
    sorted
    1
    2
    3
    4
    5
    6
    6
    22
    34
    45

    只使用堆排序,静态方法

    public class HeapSort{
    
        public static void sink(Comparable[] arr, int k, int n){  //使用了多态,要求数组实现Comparable接口
            while (2*k<=n){//有子节点
                int j=2*k;
                if(j+1<=n && less(arr,j,j+1)) j++;
                if(less(arr,j,k)) break;
                exch(arr,j,k);
                k=j;   //k表示父节点、j表示较大的子节点。
            }
        }
    
        public static boolean less(Comparable[] arr,int a,int b){
            if(arr[a].compareTo(arr[b])<0) return true;
            return false;
        }
    
        public static void exch(Comparable[] arr, int a,int b){
            Comparable temp = arr[a];
            arr[a] = arr[b];
            arr[b] = temp;
        }
    
        public static void sort(Comparable[] arr){
            for(int i=arr.length/2;i>=1;i--){
                sink(arr, i, arr.length-1);
            }
            int n=arr.length-1;
            while(n>1){
                exch(arr,1,n--);
                sink(arr,1,n);
            }
        }
    }
    import java.util.Arrays;
    
    /**
     * 测试案例
     */
    public class TestCase {
        public static void main(String[] args) {
            Integer[] arr = new Integer[]{0,1,6,34,2,5,3,4,45,6,22};//数组索引为0的位置不放元素
            HeapSort.sort(arr);
            System.out.println(Arrays.toString(arr));
        }
    }
    
    //结果
    [0, 1, 2, 3, 4, 5, 6, 6, 22, 34, 45]
  • 相关阅读:
    [windows菜鸟]C#中调用Windows API参考工具
    [windows菜鸟]C#中调用Windows API的技术要点说明
    [windows菜鸟]Windows API函数大全(完整)
    C#卸载加载到进程里的dll
    C# 防火墙操作之开启与关闭
    CMD命令行管道命令
    linux kernel elv_queue_empty野指针访问内核故障定位与解决
    U-Boot Driver Model领域模型设计
    linux I/O stack cache 强制刷新
    基于lcov实现的增量代码UT覆盖率检查
  • 原文地址:https://www.cnblogs.com/youzoulalala/p/11094352.html
Copyright © 2011-2022 走看看