小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

java堆排序算法

 dongsibei 2014-04-24

java堆排序算法

2012-08-26 作者:神馬舉報(bào)

[java]代碼庫(kù)

/**
 * 選擇排序之堆排序:
 *
 * 1. 基本思想: 堆排序是一樹(shù)形選擇排序,在排序過(guò)程中,將R[1..N]看成是一顆完全二叉樹(shù)的順序存儲(chǔ)結(jié)構(gòu),
 * 利用完全二叉樹(shù)中雙親結(jié)點(diǎn)和孩子結(jié)點(diǎn)之間的內(nèi)在關(guān)系來(lái)選擇最小的元素。
 *
 * 2. 堆的定義: N個(gè)元素的序列K1,K2,K3,...,Kn.稱(chēng)為堆,當(dāng)且僅當(dāng)該序列滿(mǎn)足特性: Ki≤K2i Ki ≤K2i+1(1≤ I≤[N/2])
 * 堆實(shí)質(zhì)上是滿(mǎn)足如下性質(zhì)的完全二叉樹(shù):樹(shù)中任一非葉子結(jié)點(diǎn)的關(guān)鍵字均大于等于其孩子結(jié)點(diǎn)的關(guān)鍵字。例如序列10,15,56,25,30,70就是一個(gè)堆,
 * 它對(duì)應(yīng)的完全二叉樹(shù)如上圖所示。這種堆中根結(jié)點(diǎn)(稱(chēng)為堆頂)的關(guān)鍵字最小,我們把它稱(chēng)為小根堆。
 * 反之,若完全二叉樹(shù)中任一非葉子結(jié)點(diǎn)的關(guān)鍵字均大于等于其孩子的關(guān)鍵字,則稱(chēng)之為大根堆。
 *
 * 3.排序過(guò)程: 堆排序正是利用小根堆(或大根堆)來(lái)選取當(dāng)前無(wú)序區(qū)中關(guān)鍵字小(或最大)的記錄實(shí)現(xiàn)排序的。我們不妨利用大根堆來(lái)排序。每一趟排序的基本操作是:
 * 將當(dāng)前無(wú)序區(qū)調(diào)整為一個(gè)大根堆
 * ,選取關(guān)鍵字最大的堆頂記錄,將它和無(wú)序區(qū)中的最后一個(gè)記錄交換。這樣,正好和直接選擇排序相反,有序區(qū)是在原記錄區(qū)的尾部形成并逐步向前擴(kuò)大到整個(gè)記錄區(qū)。
 */
public class HeapSort {
 
    /**
     * 排序算法的實(shí)現(xiàn),對(duì)數(shù)組中指定的元素進(jìn)行排序
     *
     * @param array
     *            待排序的數(shù)組
     * @param from
     *            從哪里開(kāi)始排序
     * @param end
     *            排到哪里
     * @param c
     *            比較器
     */
    public void sort(Integer[] array, int from, int end) {
        // 創(chuàng)建初始堆
        initialHeap(array, from, end);
 
        /*
         * 對(duì)初始堆進(jìn)行循環(huán),且從最后一個(gè)節(jié)點(diǎn)開(kāi)始,直接樹(shù)只有兩個(gè)節(jié)點(diǎn)止 每輪循環(huán)后丟棄最后一個(gè)葉子節(jié)點(diǎn),再看作一個(gè)新的樹(shù)
         */
        for (int i = end - from + 1; i >= 2; i--) {
            // 根節(jié)點(diǎn)與最后一個(gè)葉子節(jié)點(diǎn)交換位置,即數(shù)組中的第一個(gè)元素與最后一個(gè)元素互換
            swap(array, from, i - 1);
            // 交換后需要重新調(diào)整堆
            adjustNote(array, 1, i - 1);
        }
 
    }
 
    /**
     * 初始化堆 比如原序列為:7,2,4,3,12,1,9,6,8,5,10,11 則初始堆為:1,2,4,3,5,7,9,6,8,12,10,11
     *
     * @param arr
     *            排序數(shù)組
     * @param from
     *            從哪
     * @param end
     *            到哪
     * @param c
     *            比較器
     */
    private void initialHeap(Integer[] arr, int from, int end) {
        int lastBranchIndex = (end - from + 1) / 2;// 最后一個(gè)非葉子節(jié)點(diǎn)
        // 對(duì)所有的非葉子節(jié)點(diǎn)進(jìn)行循環(huán) ,且從最一個(gè)非葉子節(jié)點(diǎn)開(kāi)始
        for (int i = lastBranchIndex; i >= 1; i--) {
            adjustNote(arr, i, end - from + 1);
        }
    }
 
    /**
     * 調(diào)整節(jié)點(diǎn)順序,從父、左右子節(jié)點(diǎn)三個(gè)節(jié)點(diǎn)中選擇一個(gè)最大節(jié)點(diǎn)與父節(jié)點(diǎn)轉(zhuǎn)換
     *
     * @param arr
     *            待排序數(shù)組
     * @param parentNodeIndex
     *            要調(diào)整的節(jié)點(diǎn),與它的子節(jié)點(diǎn)一起進(jìn)行調(diào)整
     * @param len
     *            樹(shù)的節(jié)點(diǎn)數(shù)
     * @param c
     *            比較器
     */
    private void adjustNote(Integer[] arr, int parentNodeIndex, int len) {
        int minNodeIndex = parentNodeIndex;
        // 如果有左子樹(shù),i * 2為左子節(jié)點(diǎn)索引
        if (parentNodeIndex * 2 <= len) {
            // 如果父節(jié)點(diǎn)小于左子樹(shù)時(shí)
            if ((arr[parentNodeIndex - 1]
                    .compareTo(arr[parentNodeIndex * 2 - 1])) < 0) {
                minNodeIndex = parentNodeIndex * 2;// 記錄最大索引為左子節(jié)點(diǎn)索引
            }
 
            // 只有在有或子樹(shù)的前提下才可能有右子樹(shù),再進(jìn)一步斷判是否有右子樹(shù)
            if (parentNodeIndex * 2 + 1 <= len) {
                // 如果右子樹(shù)比最大節(jié)點(diǎn)更大
                if ((arr[minNodeIndex - 1]
                        .compareTo(arr[(parentNodeIndex * 2 + 1) - 1])) < 0) {
                    minNodeIndex = parentNodeIndex * 2 + 1;// 記錄最大索引為右子節(jié)點(diǎn)索引
                }
            }
        }
 
        // 如果在父節(jié)點(diǎn)、左、右子節(jié)點(diǎn)三都中,最大節(jié)點(diǎn)不是父節(jié)點(diǎn)時(shí)需交換,把最大的與父節(jié)點(diǎn)交換,創(chuàng)建大頂堆
        if (minNodeIndex != parentNodeIndex) {
            swap(arr, parentNodeIndex - 1, minNodeIndex - 1);
            // 交換后可能需要重建堆,原父節(jié)點(diǎn)可能需要繼續(xù)下沉
            if (minNodeIndex * 2 <= len) {// 是否有子節(jié)點(diǎn),注,只需判斷是否有左子樹(shù)即可知道
                adjustNote(arr, minNodeIndex, len);
            }
        }
    }
 
    /**
     * 交換數(shù)組中的兩個(gè)元素的位置
     *
     * @param array
     *            待交換的數(shù)組
     * @param i
     *            第一個(gè)元素
     * @param j
     *            第二個(gè)元素
     */
    public void swap(Integer[] array, int i, int j) {
        if (i != j) {// 只有不是同一位置時(shí)才需交換
            Integer tmp = array[i];
            array[i] = array[j];
            array[j] = tmp;
        }
    }
 
    /**
     * 測(cè)試
     *
     * @param args
     */
    public static void main(String[] args) {
        Integer[] intgArr = { 5, 9, 1, 4, 2, 6, 3, 8, 0, 7, 0, -7, -1, 34 };
        HeapSort heapsort = new HeapSort();
        heapsort.sort(intgArr, 0, intgArr.length - 1);
        for (Integer intObj : intgArr) {
            System.out.print(intObj + " ");
        }
    }
 
}

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多