Java 堆排序(大根堆及小根堆)

来源:互联网 发布:叶修手办淘宝 编辑:程序博客网 时间:2024/06/18 00:00

整理网上的最大堆及最小堆代码

public abstract class Sorter {    public abstract void sort(int[] array);}
public class HeapSorter extends Sorter {    @Override    public void sort(int[] array) {        heapSort(array);    }    /**     * 堆排序方法     * 基于大根堆实现     * @param array     */    private void heapSort(int[] array) {        Integer tmp;//暂存交换元素        buildHeap(array);//执行初始建堆,并调整        for (int i=0;i<array.length;i++){            // 交换堆顶元素array[0]和堆中最后一个元素array[array.length-1-i]            tmp=array[0];            array[0]=array[array.length-i-1];            array[array.length-i-1]=tmp;            // 每次交换堆顶元素和堆中最后一个元素之后,都要对堆进行调整            adjustHeap(array,0,array.length-i-1);        }    }    /**     * <p>     * 调整堆的方法     * @param i 待调整结点的索引     * @param m 待调整堆的结点的数量(即:排除叶子结点)     */    private void adjustHeap(int[] array, int i, int m) {        Integer tmp = array[i]; // 当前待调整的结点        int s = 2 * i + 1; // 当前待调整结点的左孩子结点的索引(s+1为当前调整结点的右孩子结点的索引)        while (s < m) {            if (s + 1 < m && array[s] < array[s + 1]) { // 如果右孩子大于左孩子(找到比当前待调整结点大的孩子结点)                s=s+1;            }            if (array[i]<array[s]){                array[i]=array[s];// 孩子结点大于当前待调整结点,将孩子结点放到当前待调整结点的位置上                i=s;// 重新设置待调整的下一个结点的索引                s=2*i+1;            }else{// 如果当前待调整结点大于它的左右孩子,则不需要调整,直接退出                break;            }            array[i]=tmp;// 当前待调整的结点放到比其大的孩子结点位置上        }    }    /**     * 建堆方法     * 并调整0-array.length/2个节点,保持堆的性质     * @param array     */    private void buildHeap(int[] array) {        // 求出当前堆中最后一个存在孩子结点的索引        int pos=(array.length-1)/2;        // 从该结点结点开始,执行建堆操作        for (int i=pos;i>=0;i--){            adjustHeap(array,i,array.length);// 在建堆过程中,及时调整堆中索引为i的结点        }    }    /**     * 最小堆     * @param a     * @param n     */    //构建最小堆    public static void MakeMinHeap(int a[], int n){        for(int i=(n-1)/2 ; i>=0 ; i--){            MinHeapFixdown(a,i,n);        }    }    //从i节点开始调整,n为节点总数 从0开始计算 i节点的子节点为 2*i+1, 2*i+2    public static void MinHeapFixdown(int a[],int i,int n){        int j = 2*i+1; //子节点        int temp = 0;        while(j<n){            //在左右子节点中寻找最小的            if(j+1<n && a[j+1]<a[j]){                j++;            }            if(a[i] <= a[j])                break;            //较大节点下移            temp = a[i];            a[i] = a[j];            a[j] = temp;            i = j;            j = 2*i+1;        }    }    public static void MinHeap_Sort(int a[],int n){        int temp = 0;        MakeMinHeap(a,n);        for(int i=n-1;i>0;i--){            temp = a[0];            a[0] = a[i];            a[i] = temp;            MinHeapFixdown(a,0,i);        }    }    public static void main(String[] args) {        int array[]={1,6,9,45,65,12,3,4,578,78,5,6,13,458,12,456,789,123};        HeapSorter heapSorter=new HeapSorter();        heapSorter.heapSort(array);//        heapSorter.MinHeap_Sort(array,array.length);        for (int i:array){            System.out.print(i+" ");        }        System.out.println(" ");    }}