成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

堆排序Java實(shí)現(xiàn)(遞歸方式&非遞歸方式)

jzman / 1161人閱讀

摘要:很早就學(xué)習(xí)了堆排序但當(dāng)時(shí)沒(méi)有用代碼實(shí)現(xiàn),現(xiàn)在再去想實(shí)現(xiàn)已經(jīng)忘光光啦,于是就去網(wǎng)上搜了一番,發(fā)現(xiàn)沒(méi)有一篇我能認(rèn)真看完的文章,沒(méi)辦法就是沒(méi)耐心,就是笨唄。。。

很早就學(xué)習(xí)了堆排序但當(dāng)時(shí)沒(méi)有用代碼實(shí)現(xiàn),現(xiàn)在再去想實(shí)現(xiàn)已經(jīng)忘光光啦┑( ̄Д  ̄)┍,于是就去網(wǎng)上搜了一番,發(fā)現(xiàn)沒(méi)有一篇我能認(rèn)真看完的文章,沒(méi)辦法就是沒(méi)耐心,就是笨唄。。。好了,言歸正傳= ̄ω ̄=

了解概念

首先明白什么是堆,什么是完全二叉樹(shù),什么是大頂堆,相信百度一下很容易理解o(^▽^)o。

堆可以用數(shù)組來(lái)存儲(chǔ),如下圖,數(shù)組 a[0,...,9] 表示一個(gè)堆在數(shù)組中的存儲(chǔ)模式。數(shù)組中下標(biāo)為i的節(jié)點(diǎn)的子節(jié)點(diǎn)下標(biāo)分別為2*i+12*i+2,下標(biāo)為j的子節(jié)點(diǎn)的父節(jié)點(diǎn)下標(biāo)為(j-1)/2

算法描述

將待排序數(shù)組構(gòu)建成一個(gè)大頂堆,也就是變換原始數(shù)組中元素的位置,使之滿足大頂堆的定義。

將堆頂節(jié)點(diǎn)與堆中末尾節(jié)點(diǎn)交換,也就是數(shù)組的首尾元素交換,此時(shí)末尾節(jié)點(diǎn)已為最大元素,考慮剩余節(jié)點(diǎn)形成的堆。

將最新的堆重新構(gòu)造成大頂堆。

重復(fù)第2步、第3步直到堆中節(jié)點(diǎn)全部輸出。

建議不明白的同學(xué)觀看視頻https://www.bilibili.com/vide...

算法實(shí)現(xiàn)
public class HeapSort {

    public static void heapSort(int[] array) {
        array = buildMaxHeap(array); //初始建堆,array[0]為第一趟值最大的元素
        for (int i = array.length - 1; i >= 1; i--) {
            int temp = array[0];  //將堆頂元素和堆底元素交換,即得到當(dāng)前最大元素正確的排序位置
            array[0] = array[i];
            array[i] = temp;
            adjustHeap1(array, 0, i);  //整理,將剩余的元素整理成大頂堆
        }
    }

    //自下而上構(gòu)建大頂堆:將array看成完全二叉樹(shù)的順序存儲(chǔ)結(jié)構(gòu)
    private static int[] buildMaxHeap(int[] array) {
        //從最后一個(gè)節(jié)點(diǎn)array.length-1的父節(jié)點(diǎn)(array.length-1-1)/2開(kāi)始,直到根節(jié)點(diǎn)0,反復(fù)調(diào)整堆
        for(int i=(array.length-2)/2;i>=0;i--){
            adjustHeap1(array, i, array.length);
        }
        return array;

    }

    //自上而下調(diào)整大頂堆(非遞歸)
    private static void adjustHeap1(int[] array, int k, int length) {
        int temp = array[k]; //堆頂節(jié)點(diǎn)
        for (int i = 2*k+1; i <= length - 1; i = 2*i+1) {    //i為初始化為節(jié)點(diǎn)k的左孩子,沿節(jié)點(diǎn)較大的子節(jié)點(diǎn)向下調(diào)整

            if (i+1< length && array[i] < array[i + 1]) {  //如果左孩子小于右孩子
                i++;   //則取右孩子節(jié)點(diǎn)的下標(biāo)
            }
            if (temp >= array[i]) {  //堆頂節(jié)點(diǎn) >=左右孩子中較大者,調(diào)整結(jié)束
                break;
            } else {   //根節(jié)點(diǎn) < 左右子女中關(guān)鍵字較大者
                array[k] = array[i];  //將左右子結(jié)點(diǎn)中較大值array[i]調(diào)整到雙親節(jié)點(diǎn)上
                k = i; //【關(guān)鍵】修改k值,以便繼續(xù)向下調(diào)整
            }
        }
        array[k] = temp;  //被堆頂結(jié)點(diǎn)的值放人最終位置
        
    }

    //自上而下調(diào)整大頂堆(遞歸)
    private static void adjustHeap2(int[] array, int k, int length) {
        int k1=2*k+1;  
        if(k1length-1||array[k]>=array[k1]){
            return;
        }else{
            int temp = array[k];  //將堆頂元素和左右子結(jié)點(diǎn)中較大節(jié)點(diǎn)交換
            array[k] = array[k1];
            array[k1] = temp;
            adjustHeap2(array,k1,length);
        }
    }
    
    

    public static void main(String[] args) {
        int[] a = {87,45,78,32,17,65,53,9,122,133};
        heapSort(a);
        System.out.println(Arrays.toString(a));
    }
}
算法復(fù)雜度

堆排序時(shí)間計(jì)算分兩部分,構(gòu)建堆時(shí)間復(fù)雜度O(n),調(diào)整堆時(shí)間復(fù)雜度O(nlogn),總的時(shí)間復(fù)雜度O(nlogn),堆排序?yàn)榫偷嘏判?,空間復(fù)雜度O(1)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/72593.html

相關(guān)文章

  • 排序

    摘要:計(jì)算機(jī)算法理論簡(jiǎn)介建立初始堆首末元素互換即得到最大元素放入數(shù)組最末尾調(diào)整堆第二步的操作明顯會(huì)將堆破壞所以需要調(diào)整堆跳回第二步建立初始堆在建堆之前需要將數(shù)組轉(zhuǎn)成二叉樹(shù)圖方便理解如果將父左子右子當(dāng)做樹(shù)的最小單元組稱為父子單元那么只需要保證每個(gè)父 @(Study)[計(jì)算機(jī), 算法] 理論簡(jiǎn)介 建立初始堆 首末元素互換, 即得到最大元素放入數(shù)組最末尾. 調(diào)整堆. 第二步的操作明顯會(huì)將堆破壞,...

    tangr206 評(píng)論0 收藏0
  • 數(shù)據(jù)結(jié)構(gòu)與算法——常用數(shù)據(jù)結(jié)構(gòu)及其Java實(shí)現(xiàn)

    摘要:亦即總結(jié)常見(jiàn)的的數(shù)據(jù)結(jié)構(gòu),以及在中相應(yīng)的實(shí)現(xiàn)方法,務(wù)求理論與實(shí)踐一步總結(jié)到位。中,使用鏈表作為其基礎(chǔ)實(shí)現(xiàn)。其限制是僅允許在表的一端進(jìn)行插入和刪除運(yùn)算。 前言 仿佛一下子,2017年就快過(guò)去一半了,研一馬上就要成為過(guò)去式了,我打算抓住研一的尾巴,好好梳理一下數(shù)據(jù)結(jié)構(gòu)與算法,畢竟這些基礎(chǔ)知識(shí)是很重要的嘛。所以準(zhǔn)備在這里搞一個(gè)系列的文章,以期透徹。 本系列將采用Java語(yǔ)言來(lái)進(jìn)行描述。亦即總...

    RiverLi 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<