欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實(shí)現(xiàn)堆排序(大根堆)的示例代碼

 更新時(shí)間:2019年10月24日 10:45:17   作者:sunshisonghit  
這篇文章主要介紹了Java實(shí)現(xiàn)堆排序(大根堆)的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

堆排序是一種樹形選擇排序方法,它的特點(diǎn)是:在排序的過程中,將array[0,...,n-1]看成是一顆完全二叉樹的順序存儲(chǔ)結(jié)構(gòu),利用完全二叉樹中雙親節(jié)點(diǎn)和孩子結(jié)點(diǎn)之間的內(nèi)在關(guān)系,在當(dāng)前無序區(qū)中選擇關(guān)鍵字最大(最?。┑脑?。

1. 若array[0,...,n-1]表示一顆完全二叉樹的順序存儲(chǔ)模式,則雙親節(jié)點(diǎn)指針和孩子結(jié)點(diǎn)指針之間的內(nèi)在關(guān)系如下:

任意一節(jié)點(diǎn)指針 i:父節(jié)點(diǎn):i==0 ? null : (i-1)/2

        左孩子:2*i + 1

        右孩子:2*i + 2

2. 堆的定義:n個(gè)關(guān)鍵字序列array[0,...,n-1],當(dāng)且僅當(dāng)滿足下列要求:(0 <= i <= (n-1)/2)

     ?、?array[i] <= array[2*i + 1] 且 array[i] <= array[2*i + 2]; 稱為小根堆;

     ?、?array[i] >= array[2*i + 1] 且 array[i] >= array[2*i + 2]; 稱為大根堆;

3. 建立大根堆:

n個(gè)節(jié)點(diǎn)的完全二叉樹array[0,...,n-1],最后一個(gè)節(jié)點(diǎn)n-1是第(n-1-1)/2個(gè)節(jié)點(diǎn)的孩子。對(duì)第(n-1-1)/2個(gè)節(jié)點(diǎn)為根的子樹調(diào)整,使該子樹稱為堆。

對(duì)于大根堆,調(diào)整方法為:若【根節(jié)點(diǎn)的關(guān)鍵字】小于【左右子女中關(guān)鍵字較大者】,則交換。

之后向前依次對(duì)各節(jié)點(diǎn)((n-2)/2 - 1)~ 0為根的子樹進(jìn)行調(diào)整,看該節(jié)點(diǎn)值是否大于其左右子節(jié)點(diǎn)的值,若不是,將左右子節(jié)點(diǎn)中較大值與之交換,交換后可能會(huì)破壞下一級(jí)堆,于是繼續(xù)采用上述方法構(gòu)建下一級(jí)的堆,直到以該節(jié)點(diǎn)為根的子樹構(gòu)成堆為止。

反復(fù)利用上述調(diào)整堆的方法建堆,直到根節(jié)點(diǎn)。

4.堆排序:(大根堆)

  ①將存放在array[0,...,n-1]中的n個(gè)元素建成初始堆;

 ?、趯⒍秧斣嘏c堆底元素進(jìn)行交換,則序列的最大值即已放到正確的位置;

  ③但此時(shí)堆被破壞,將堆頂元素向下調(diào)整使其繼續(xù)保持大根堆的性質(zhì),再重復(fù)第②③步,直到堆中僅剩下一個(gè)元素為止。

堆排序算法的性能分析:

  空間復(fù)雜度:o(1);

  時(shí)間復(fù)雜度:建堆:o(n),每次調(diào)整o(log n),故最好、最壞、平均情況下:o(n*logn);

  穩(wěn)定性:不穩(wěn)定

建立大根堆的方法:

//構(gòu)建大根堆:將array看成完全二叉樹的順序存儲(chǔ)結(jié)構(gòu)
  private int[] buildMaxHeap(int[] array){
    //從最后一個(gè)節(jié)點(diǎn)array.length-1的父節(jié)點(diǎn)(array.length-1-1)/2開始,直到根節(jié)點(diǎn)0,反復(fù)調(diào)整堆
    for(int i=(array.length-2)/2;i>=0;i--){ 
      adjustDownToUp(array, i,array.length);
    }
    return array;
  }
  
  //將元素array[k]自下往上逐步調(diào)整樹形結(jié)構(gòu)
  private void adjustDownToUp(int[] array,int k,int length){
    int temp = array[k];  
    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<length && array[i]<array[i+1]){ //取節(jié)點(diǎn)較大的子節(jié)點(diǎn)的下標(biāo)
        i++;  //如果節(jié)點(diǎn)的右孩子>左孩子,則取右孩子節(jié)點(diǎn)的下標(biāo)
      }
      if(temp>=array[i]){ //根節(jié)點(diǎn) >=左右子女中關(guā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; //被調(diào)整的結(jié)點(diǎn)的值放人最終位置
  }

堆排序:

//堆排序
  public int[] 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;
      adjustDownToUp(array, 0,i); //整理,將剩余的元素整理成堆
    }
    return array;
  }

刪除堆頂元素(即序列中的最大值):先將堆的最后一個(gè)元素與堆頂元素交換,由于此時(shí)堆的性質(zhì)被破壞,需對(duì)此時(shí)的根節(jié)點(diǎn)進(jìn)行向下調(diào)整操作。

//刪除堆頂元素操作
  public int[] deleteMax(int[] array){
    //將堆的最后一個(gè)元素與堆頂元素交換,堆底元素值設(shè)為-99999
    array[0] = array[array.length-1];
    array[array.length-1] = -99999;
    //對(duì)此時(shí)的根節(jié)點(diǎn)進(jìn)行向下調(diào)整
    adjustDownToUp(array, 0, array.length);
    return array;
  }

對(duì)堆的插入操作:先將新節(jié)點(diǎn)放在堆的末端,再對(duì)這個(gè)新節(jié)點(diǎn)執(zhí)行向上調(diào)整操作。

假設(shè)數(shù)組的最后一個(gè)元素array[array.length-1]為空,新插入的結(jié)點(diǎn)初始時(shí)放置在此處。

//插入操作:向大根堆a(bǔ)rray中插入數(shù)據(jù)data
  public int[] insertData(int[] array, int data){
    array[array.length-1] = data; //將新節(jié)點(diǎn)放在堆的末端
    int k = array.length-1; //需要調(diào)整的節(jié)點(diǎn)
    int parent = (k-1)/2;  //雙親節(jié)點(diǎn)
    while(parent >=0 && data>array[parent]){
      array[k] = array[parent]; //雙親節(jié)點(diǎn)下調(diào)
      k = parent;
      if(parent != 0){
        parent = (parent-1)/2; //繼續(xù)向上比較
      }else{ //根節(jié)點(diǎn)已調(diào)整完畢,跳出循環(huán)
        break;
      }
    }
    array[k] = data; //將插入的結(jié)點(diǎn)放到正確的位置
    return array;
  }

測試:

public void toString(int[] array){
    for(int i:array){
      System.out.print(i+" ");
    }
  }
  
  public static void main(String args[]){
    HeapSort hs = new HeapSort();
    int[] array = {87,45,78,32,17,65,53,9,122};
    System.out.print("構(gòu)建大根堆:");
    hs.toString(hs.buildMaxHeap(array));
    System.out.print("\n"+"刪除堆頂元素:");
    hs.toString(hs.deleteMax(array));
    System.out.print("\n"+"插入元素63:");
    hs.toString(hs.insertData(array, 63));
    System.out.print("\n"+"大根堆排序:");
    hs.toString(hs.heapSort(array));  
  }

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • RocketMQ的四種常用消息隊(duì)列及代碼演示

    RocketMQ的四種常用消息隊(duì)列及代碼演示

    這篇文章主要介紹了RocketMQ的四種常用消息隊(duì)列及代碼演示,普通消息隊(duì)列是最基本的一種消息隊(duì)列,可以按照先進(jìn)先出(FIFO)的順序存儲(chǔ)消息,并且可以被多個(gè)消費(fèi)者同時(shí)消費(fèi),可以通過在生產(chǎn)者端指定主題名稱和標(biāo)簽來創(chuàng)建普通消息隊(duì)列,需要的朋友可以參考下
    2024-01-01
  • java通過PDF模板填寫PDF表單

    java通過PDF模板填寫PDF表單

    這篇文章主要為大家詳細(xì)介紹了java通過PDF模板填寫PDF表單,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • JAVA異常處理捕獲與拋出原理解析

    JAVA異常處理捕獲與拋出原理解析

    這篇文章主要介紹了JAVA異常處理捕獲與拋出原理解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • SpringBoot中的自定義starter

    SpringBoot中的自定義starter

    這篇文章主要介紹了SpringBoot中的自定義starter,Starter是Spring?Boot中的一個(gè)非常重要的概念,Starter相當(dāng)于模塊,它能將模塊所需的依賴整合起來并對(duì)模塊內(nèi)的Bean根據(jù)環(huán)境(條件)進(jìn)行自動(dòng)配置,需要的朋友可以參考下
    2024-01-01
  • Java中MyBatis傳入?yún)?shù)parameterType問題

    Java中MyBatis傳入?yún)?shù)parameterType問題

    這篇文章主要介紹了Java中MyBatis傳入?yún)?shù)parameterType問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • 關(guān)于Assert.assertEquals報(bào)錯(cuò)的問題及解決

    關(guān)于Assert.assertEquals報(bào)錯(cuò)的問題及解決

    這篇文章主要介紹了關(guān)于Assert.assertEquals報(bào)錯(cuò)的問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • idea創(chuàng)建springboot項(xiàng)目和springcloud項(xiàng)目的詳細(xì)教程

    idea創(chuàng)建springboot項(xiàng)目和springcloud項(xiàng)目的詳細(xì)教程

    這篇文章主要介紹了idea創(chuàng)建springboot項(xiàng)目和springcloud項(xiàng)目方法,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • java 相交鏈表的實(shí)現(xiàn)示例

    java 相交鏈表的實(shí)現(xiàn)示例

    本文主要介紹了java 相交鏈表的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Spring5+SpringMvc+Hibernate5整合的實(shí)現(xiàn)

    Spring5+SpringMvc+Hibernate5整合的實(shí)現(xiàn)

    這篇文章主要介紹了Spring5+SpringMvc+Hibernate5整合的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • 淺談Spring Data Redis讀不到設(shè)進(jìn)去的值

    淺談Spring Data Redis讀不到設(shè)進(jìn)去的值

    本文主要介紹了Spring Data Redis怎么讀不到我剛才設(shè)進(jìn)去的值,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09

最新評(píng)論