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

Java堆排序算法詳解

 更新時間:2021年11月04日 15:28:07   作者:Amedeo  
這篇文章主要為大家詳細介紹了Java堆排序算法的相關(guān)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下

堆是數(shù)據(jù)結(jié)構(gòu)中的一種重要結(jié)構(gòu),了解“堆”的概念和操作,可以幫助我們快速地掌握堆排序。

堆的概念

堆是一種特殊的完全二叉樹(complete binary tree)。如果一棵完全二叉樹的所有節(jié)點的值都不小于其子節(jié)點,稱之為大根堆(或大頂堆);所有節(jié)點的值都不大于其子節(jié)點,稱之為小根堆(或小頂堆)。

在數(shù)組(在0號下標存儲根節(jié)點)中,容易得到下面的式子(這兩個式子很重要):

1.下標為i的節(jié)點,父節(jié)點坐標為(i-1)/2;

2.下標為i的節(jié)點,左子節(jié)點坐標為2*i+1,右子節(jié)點為2*i+2。

堆的建立和維護

堆可以支持多種操作,但現(xiàn)在我們關(guān)心的只有兩個問題:

1.給定一個無序數(shù)組,如何建立為堆?

2.刪除堆頂元素后,如何調(diào)整數(shù)組成為新堆?

先看第二個問題。假定我們已經(jīng)有一個現(xiàn)成的大根堆?,F(xiàn)在我們刪除了根元素,但并沒有移動別的元素。想想發(fā)生了什么:根元素空了,但其它元素還保持著堆的性質(zhì)。我們可以把最后一個元素(代號A)移動到根元素的位置。如果不是特殊情況,則堆的性質(zhì)被破壞。但這僅僅是由于A小于其某個子元素。于是,我們可以把A和這個子元素調(diào)換位置。如果A大于其所有子元素,則堆調(diào)整好了;否則,重復(fù)上述過程,A元素在樹形結(jié)構(gòu)中不斷“下沉”,直到合適的位置,數(shù)組重新恢復(fù)堆的性質(zhì)。上述過程一般稱為“篩選”,方向顯然是自上而下。

刪除一個元素是如此,插入一個新元素也是如此。不同的是,我們把新元素放在末尾,然后和其父節(jié)點做比較,即自下而上篩選。

那么,第一個問題怎么解決呢?

我看過的數(shù)據(jù)結(jié)構(gòu)的書很多都是從第一個非葉子結(jié)點向下篩選,直到根元素篩選完畢。這個方法叫“篩選法”,需要循環(huán)篩選n/2個元素。

但我們還可以借鑒“無中生有”的思路。我們可以視第一個元素為一個堆,然后不斷向其中添加新元素。這個方法叫做“插入法”,需要循環(huán)插入(n-1)個元素。

由于篩選法和插入法的方式不同,所以,相同的數(shù)據(jù),它們建立的堆一般不同。

大致了解堆之后,堆排序就是水到渠成的事情了。

算法概述/思路

我們需要一個升序的序列,怎么辦呢?我們可以建立一個最小堆,然后每次輸出根元素。但是,這個方法需要額外的空間(否則將造成大量的元素移動,其復(fù)雜度會飆升到O(n^2))。如果我們需要就地排序(即不允許有O(n)空間復(fù)雜度),怎么辦?
有辦法。我們可以建立最大堆,然后我們倒著輸出,在最后一個位置輸出最大值,次末位置輸出次大值……由于每次輸出的最大元素會騰出第一個空間,因此,我們恰好可以放置這樣的元素而不需要額外空間。很漂亮的想法,是不是?

public class HeapSort 
{
  public static void main(String[] args) 
  {
    int[] arr = { 50, 10, 90, 30, 70, 40, 80, 60, 20 };
    System.out.println("排序之前:"); 
    for (int i = 0; i < arr.length; i++) 
      System.out.print(arr[i] + " "); 
    
    // 堆排序
    heapSort(arr); 
    System.out.println(); 
    System.out.println("排序之后:"); 
    for (int i = 0; i < arr.length; i++) 
      System.out.print(arr[i] + " ");
  }
  
  /** 
  * 堆排序 
  */
  private static void heapSort(int[] arr) 
  {
    // 將待排序的序列構(gòu)建成一個大頂堆 
    for (int i = arr.length / 2; i >= 0; i--)
      heapAdjust(arr, i, arr.length);
    
    // 逐步將每個最大值的根節(jié)點與末尾元素交換,并且再調(diào)整二叉樹,使其成為大頂堆 
    for (int i = arr.length - 1; i > 0; i--)
    {
      swap(arr, 0, i); // 將堆頂記錄和當(dāng)前未經(jīng)排序子序列的最后一個記錄交換 
      heapAdjust(arr, 0, i); // 交換之后,需要重新檢查堆是否符合大頂堆,不符合則要調(diào)整
    }
  }
  /** 
  * 構(gòu)建堆的過程 
  * @param arr 需要排序的數(shù)組 
  * @param i 需要構(gòu)建堆的根節(jié)點的序號 
  * @param n 數(shù)組的長度 
  */
  private static void heapAdjust(int[] arr, int i, int n) 
  {
    int child;
    int father;
    for (father = arr[i]; leftChild(i) < n; i = child)
    {
      child = leftChild(i);
      // 如果左子樹小于右子樹,則需要比較右子樹和父節(jié)點 
      if (child != n - 1 && arr[child] < arr[child + 1])
        child++; // 序號增1,指向右子樹
      // 如果父節(jié)點小于孩子結(jié)點,則需要交換 
      if (father < arr[child]) 
        arr[i] = arr[child];
      else
        break; // 大頂堆結(jié)構(gòu)未被破壞,不需要調(diào)整
    }
    arr[i] = father;
  }
  
  // 獲取到左孩子結(jié)點 
  private static int leftChild(int i) 
  {
    return 2 * i + 1;
  }
  
  // 交換元素位置 
  private static void swap(int[] arr, int index1, int index2) 
  {
    int tmp = arr[index1];
    arr[index1] = arr[index2];
    arr[index2] = tmp;
  }
}

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

相關(guān)文章

  • RabbitMQ 的消息持久化與 Spring AMQP 的實現(xiàn)詳解

    RabbitMQ 的消息持久化與 Spring AMQP 的實現(xiàn)詳解

    這篇文章主要介紹了RabbitMQ 的消息持久化與 Spring AMQP 的實現(xiàn)剖析詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-08-08
  • IDEA巧用Postfix Completion讓碼速起飛(小技巧)

    IDEA巧用Postfix Completion讓碼速起飛(小技巧)

    這篇文章主要介紹了IDEA巧用Postfix Completion讓碼速起飛,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • Java正則多字符串匹配替換

    Java正則多字符串匹配替換

    正則表達式異常強大,一直理解不深,用的也不深,這次項目中嘗試,體會到了它的強大之處。字符串查找,匹配,替換,正則無不能做,特別是靈活的運用子串匹配得到的變量值$1,$2,再進行二次處理能夠達到很巧妙的效果。
    2013-02-02
  • mybatis plus in方法使用詳解

    mybatis plus in方法使用詳解

    這篇文章主要介紹了mybatis plus in方法使用詳解,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • Java多線程的sleep休眠的實現(xiàn)

    Java多線程的sleep休眠的實現(xiàn)

    本文主要介紹了Java多線程的sleep休眠的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 基于JAVA代碼 獲取手機基本信息(本機號碼,SDK版本,系統(tǒng)版本,手機型號)

    基于JAVA代碼 獲取手機基本信息(本機號碼,SDK版本,系統(tǒng)版本,手機型號)

    本文給大家介紹基于java代碼獲取手機基本信息,包括獲取電話管理對象、獲取手機號碼、獲取手機型號、獲取SDK版本、獲取系統(tǒng)版本等相關(guān)信息,對本文感興趣的朋友一起學(xué)習(xí)吧
    2015-12-12
  • Java實現(xiàn)九九乘法表的小例子

    Java實現(xiàn)九九乘法表的小例子

    九九乘法表一般為三角形,每個數(shù)分別和從1到自身的數(shù)相乘然后把結(jié)果列出來,即要用到兩層循環(huán),外層是從1到9for(i=1;i<=9;i++),內(nèi)層是當(dāng)前數(shù)和從1到自身相乘for(j=1;j<=i;j++)
    2013-09-09
  • Java?如何接收kernel傳過來的數(shù)組(推薦)

    Java?如何接收kernel傳過來的數(shù)組(推薦)

    這篇文章主要介紹了Java?如何接收kernel傳過來的數(shù)組,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2024-08-08
  • SWT(JFace)體驗之StyledText類

    SWT(JFace)體驗之StyledText類

    有的時候Text需要實現(xiàn)這種那種的樣式。先提供在不使用StyledText類的情況:
    2009-06-06
  • java根據(jù)富文本生成pdf文件過程解析

    java根據(jù)富文本生成pdf文件過程解析

    這篇文章主要介紹了java根據(jù)富文本生成pdf文件過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-10-10

最新評論