Rumah Java javaTutorial 堆排序算法的讲解及Java版实现

堆排序算法的讲解及Java版实现

Jan 18, 2017 pm 05:04 PM

堆是数据结构中的一种重要结构,了解了“堆”的概念和操作,可以快速掌握堆排序。

堆的概念
堆是一种特殊的完全二叉树(complete binary tree)。如果一棵完全二叉树的所有节点的值都不小于其子节点,称之为大根堆(或大顶堆);所有节点的值都不大于其子节点,称之为小根堆(或小顶堆)。
在数组(在0号下标存储根节点)中,容易得到下面的式子(这两个式子很重要):
1.下标为i的节点,父节点坐标为(i-1)/2;
2.下标为i的节点,左子节点坐标为2*i+1,右子节点为2*i+2。

堆的建立和维护
堆可以支持多种操作,但现在我们关心的只有两个问题:
1.给定一个无序数组,如何建立为堆?
2.删除堆顶元素后,如何调整数组成为新堆?
先看第二个问题。假定我们已经有一个现成的大根堆。现在我们删除了根元素,但并没有移动别的元素。想想发生了什么:根元素空了,但其它元素还保持着堆的性质。我们可以把最后一个元素(代号A)移动到根元素的位置。如果不是特殊情况,则堆的性质被破坏。但这仅仅是由于A小于其某个子元素。于是,我们可以把A和这个子元素调换位置。如果A大于其所有子元素,则堆调整好了;否则,重复上述过程,A元素在树形结构中不断“下沉”,直到合适的位置,数组重新恢复堆的性质。上述过程一般称为“筛选”,方向显然是自上而下。
删除一个元素是如此,插入一个新元素也是如此。不同的是,我们把新元素放在末尾,然后和其父节点做比较,即自下而上筛选。
那么,第一个问题怎么解决呢?
我看过的数据结构的书很多都是从第一个非叶子结点向下筛选,直到根元素筛选完毕。这个方法叫“筛选法”,需要循环筛选n/2个元素。
但我们还可以借鉴“无中生有”的思路。我们可以视第一个元素为一个堆,然后不断向其中添加新元素。这个方法叫做“插入法”,需要循环插入(n-1)个元素。
由于筛选法和插入法的方式不同,所以,相同的数据,它们建立的堆一般不同。

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

算法概述/思路
我们需要一个升序的序列,怎么办呢?我们可以建立一个最小堆,然后每次输出根元素。但是,这个方法需要额外的空间(否则将造成大量的元素移动,其复杂度会飙升到O(n^2))。如果我们需要就地排序(即不允许有O(n)空间复杂度),怎么办?
有办法。我们可以建立最大堆,然后我们倒着输出,在最后一个位置输出最大值,次末位置输出次大值……由于每次输出的最大元素会腾出第一个空间,因此,我们恰好可以放置这样的元素而不需要额外空间。很漂亮的想法,是不是?

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) { 
    // 将待排序的序列构建成一个大顶堆
    for (int i = arr.length / 2; i >= 0; i--){ 
      heapAdjust(arr, i, arr.length); 
    }
      
    // 逐步将每个最大值的根节点与末尾元素交换,并且再调整二叉树,使其成为大顶堆
    for (int i = arr.length - 1; i > 0; i--) { 
      swap(arr, 0, i); // 将堆顶记录和当前未经排序子序列的最后一个记录交换
      heapAdjust(arr, 0, i); // 交换之后,需要重新检查堆是否符合大顶堆,不符合则要调整
    }
  }
  
  /**
   * 构建堆的过程
   * @param arr 需要排序的数组
   * @param i 需要构建堆的根节点的序号
   * @param n 数组的长度
   */
  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);
        
      // 如果左子树小于右子树,则需要比较右子树和父节点
      if (child != n - 1 && arr[child] < arr[child + 1]) {
        child++; // 序号增1,指向右子树
      }
        
      // 如果父节点小于孩子结点,则需要交换
      if (father < arr[child]) {
        arr[i] = arr[child];
      } else {
        break; // 大顶堆结构未被破坏,不需要调整
      }
    }
    arr[i] = father;
  }
  
  // 获取到左孩子结点
  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;
  }
}
Salin selepas log masuk

 更多堆排序算法的讲解及Java版实现相关文章请关注PHP中文网!  


Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
2 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Repo: Cara menghidupkan semula rakan sepasukan
1 bulan yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Cara mendapatkan biji gergasi
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Rangka Kerja 4 JavaScript teratas pada tahun 2025: React, Angular, Vue, Svelte Rangka Kerja 4 JavaScript teratas pada tahun 2025: React, Angular, Vue, Svelte Mar 07, 2025 pm 06:09 PM

Artikel ini menganalisis empat kerangka JavaScript teratas (React, Angular, Vue, Svelte) pada tahun 2025, membandingkan prestasi, skalabilitas, dan prospek masa depan mereka. Walaupun semuanya kekal dominan kerana komuniti dan ekosistem yang kuat, popul mereka yang relatif

Spring Boot Snakeyaml 2.0 CVE-2022-1471 Isu Tetap Spring Boot Snakeyaml 2.0 CVE-2022-1471 Isu Tetap Mar 07, 2025 pm 05:52 PM

Artikel ini menangani kelemahan CVE-2022-1471 dalam Snakeyaml, kecacatan kritikal yang membolehkan pelaksanaan kod jauh. Ia memperincikan bagaimana peningkatan aplikasi boot musim bunga ke snakeyaml 1.33 atau lebih lama mengurangkan risiko ini, menekankan bahawa kemas kini ketergantungan

Bagaimanakah saya melaksanakan caching pelbagai peringkat dalam aplikasi java menggunakan perpustakaan seperti kafein atau cache jambu? Bagaimanakah saya melaksanakan caching pelbagai peringkat dalam aplikasi java menggunakan perpustakaan seperti kafein atau cache jambu? Mar 17, 2025 pm 05:44 PM

Artikel ini membincangkan pelaksanaan caching pelbagai peringkat di Java menggunakan kafein dan cache jambu untuk meningkatkan prestasi aplikasi. Ia meliputi persediaan, integrasi, dan faedah prestasi, bersama -sama dengan Pengurusan Dasar Konfigurasi dan Pengusiran PRA Terbaik

Bagaimanakah mekanisme kelas muatan Java berfungsi, termasuk kelas yang berbeza dan model delegasi mereka? Bagaimanakah mekanisme kelas muatan Java berfungsi, termasuk kelas yang berbeza dan model delegasi mereka? Mar 17, 2025 pm 05:35 PM

Kelas kelas Java melibatkan pemuatan, menghubungkan, dan memulakan kelas menggunakan sistem hierarki dengan bootstrap, lanjutan, dan pemuat kelas aplikasi. Model delegasi induk memastikan kelas teras dimuatkan dahulu, yang mempengaruhi LOA kelas tersuai

Node.js 20: Peningkatan Prestasi Utama dan Ciri -ciri Baru Node.js 20: Peningkatan Prestasi Utama dan Ciri -ciri Baru Mar 07, 2025 pm 06:12 PM

Node.js 20 dengan ketara meningkatkan prestasi melalui penambahbaikan enjin V8, terutamanya pengumpulan sampah yang lebih cepat dan I/O. Ciri -ciri baru termasuk sokongan webassembly yang lebih baik dan alat penyahpepijatan halus, meningkatkan produktiviti pemaju dan kelajuan aplikasi.

Iceberg: Masa Depan Jadual Data Tasik Iceberg: Masa Depan Jadual Data Tasik Mar 07, 2025 pm 06:31 PM

Iceberg, format meja terbuka untuk dataset analitik yang besar, meningkatkan prestasi data dan skalabiliti. Ia menangani batasan parket/orc melalui pengurusan metadata dalaman, membolehkan evolusi skema yang cekap, perjalanan masa, serentak w

Bagaimanakah saya dapat melaksanakan teknik pengaturcaraan berfungsi di Java? Bagaimanakah saya dapat melaksanakan teknik pengaturcaraan berfungsi di Java? Mar 11, 2025 pm 05:51 PM

Artikel ini meneroka mengintegrasikan pengaturcaraan berfungsi ke dalam Java menggunakan ekspresi Lambda, API Streams, rujukan kaedah, dan pilihan. Ia menyoroti faedah seperti kebolehbacaan dan kebolehkerjaan kod yang lebih baik melalui kesimpulan dan kebolehubahan

Bagaimanakah saya boleh menggunakan JPA (Java Constence API) untuk pemetaan objek-objek dengan ciri-ciri canggih seperti caching dan malas malas? Bagaimanakah saya boleh menggunakan JPA (Java Constence API) untuk pemetaan objek-objek dengan ciri-ciri canggih seperti caching dan malas malas? Mar 17, 2025 pm 05:43 PM

Artikel ini membincangkan menggunakan JPA untuk pemetaan objek-relasi dengan ciri-ciri canggih seperti caching dan pemuatan malas. Ia meliputi persediaan, pemetaan entiti, dan amalan terbaik untuk mengoptimumkan prestasi sambil menonjolkan potensi perangkap. [159 aksara]

See all articles