一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務(wù)器之家 - 編程語(yǔ)言 - JAVA教程 - 堆排序算法的講解及Java版實(shí)現(xiàn)

堆排序算法的講解及Java版實(shí)現(xiàn)

2020-04-25 15:15飛翔的貓咪 JAVA教程

這篇文章主要介紹了堆排序算法的講解及Java版實(shí)現(xiàn),堆排序基于堆這種數(shù)據(jù)結(jié)構(gòu),在本文中對(duì)堆的概念也有補(bǔ)充介紹,需要的朋友可以參考下

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

堆的概念
堆是一種特殊的完全二叉樹(shù)(complete binary tree)。如果一棵完全二叉樹(shù)的所有節(jié)點(diǎn)的值都不小于其子節(jié)點(diǎn),稱之為大根堆(或大頂堆);所有節(jié)點(diǎn)的值都不大于其子節(jié)點(diǎn),稱之為小根堆(或小頂堆)。
在數(shù)組(在0號(hào)下標(biāo)存儲(chǔ)根節(jié)點(diǎn))中,容易得到下面的式子(這兩個(gè)式子很重要):
1.下標(biāo)為i的節(jié)點(diǎn),父節(jié)點(diǎn)坐標(biāo)為(i-1)/2;
2.下標(biāo)為i的節(jié)點(diǎn),左子節(jié)點(diǎn)坐標(biāo)為2*i+1,右子節(jié)點(diǎn)為2*i+2。

堆的建立和維護(hù)
堆可以支持多種操作,但現(xiàn)在我們關(guān)心的只有兩個(gè)問(wèn)題:
1.給定一個(gè)無(wú)序數(shù)組,如何建立為堆?
2.刪除堆頂元素后,如何調(diào)整數(shù)組成為新堆?
先看第二個(gè)問(wèn)題。假定我們已經(jīng)有一個(gè)現(xiàn)成的大根堆。現(xiàn)在我們刪除了根元素,但并沒(méi)有移動(dòng)別的元素。想想發(fā)生了什么:根元素空了,但其它元素還保持著堆的性質(zhì)。我們可以把最后一個(gè)元素(代號(hào)A)移動(dòng)到根元素的位置。如果不是特殊情況,則堆的性質(zhì)被破壞。但這僅僅是由于A小于其某個(gè)子元素。于是,我們可以把A和這個(gè)子元素調(diào)換位置。如果A大于其所有子元素,則堆調(diào)整好了;否則,重復(fù)上述過(guò)程,A元素在樹(shù)形結(jié)構(gòu)中不斷“下沉”,直到合適的位置,數(shù)組重新恢復(fù)堆的性質(zhì)。上述過(guò)程一般稱為“篩選”,方向顯然是自上而下。
刪除一個(gè)元素是如此,插入一個(gè)新元素也是如此。不同的是,我們把新元素放在末尾,然后和其父節(jié)點(diǎn)做比較,即自下而上篩選。
那么,第一個(gè)問(wèn)題怎么解決呢?
我看過(guò)的數(shù)據(jù)結(jié)構(gòu)的書(shū)很多都是從第一個(gè)非葉子結(jié)點(diǎn)向下篩選,直到根元素篩選完畢。這個(gè)方法叫“篩選法”,需要循環(huán)篩選n/2個(gè)元素。
但我們還可以借鑒“無(wú)中生有”的思路。我們可以視第一個(gè)元素為一個(gè)堆,然后不斷向其中添加新元素。這個(gè)方法叫做“插入法”,需要循環(huán)插入(n-1)個(gè)元素。
由于篩選法和插入法的方式不同,所以,相同的數(shù)據(jù),它們建立的堆一般不同。

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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)建成一個(gè)大頂堆
    for (int i = arr.length / 2; i >= 0; i--){ 
      heapAdjust(arr, i, arr.length); 
    }
     
    // 逐步將每個(gè)最大值的根節(jié)點(diǎn)與末尾元素交換,并且再調(diào)整二叉樹(shù),使其成為大頂堆
    for (int i = arr.length - 1; i > 0; i--) { 
      swap(arr, 0, i); // 將堆頂記錄和當(dāng)前未經(jīng)排序子序列的最后一個(gè)記錄交換
      heapAdjust(arr, 0, i); // 交換之后,需要重新檢查堆是否符合大頂堆,不符合則要調(diào)整
    }
  }
 
  /**
   * 構(gòu)建堆的過(guò)程
   * @param arr 需要排序的數(shù)組
   * @param i 需要構(gòu)建堆的根節(jié)點(diǎn)的序號(hào)
   * @param n 數(shù)組的長(zhǎng)度
   */
  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);
       
      // 如果左子樹(shù)小于右子樹(shù),則需要比較右子樹(shù)和父節(jié)點(diǎn)
      if (child != n - 1 && arr[child] < arr[child + 1]) {
        child++; // 序號(hào)增1,指向右子樹(shù)
      }
       
      // 如果父節(jié)點(diǎn)小于孩子結(jié)點(diǎn),則需要交換
      if (father < arr[child]) {
        arr[i] = arr[child];
      } else {
        break; // 大頂堆結(jié)構(gòu)未被破壞,不需要調(diào)整
      }
    }
    arr[i] = father;
  }
 
  // 獲取到左孩子結(jié)點(diǎn)
  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;
  }
}

 

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 无限资源在线观看完整版免费下载 | 丝瓜茄子绿巨人秋葵榴莲污 | 国色天香论坛社区在线视频 | 男人与禽交的方法 | 99re视频精品全部免费 | 明星h文集合短篇小说 | 男人肌肌捅女人 | 亚州精品视频 | 催奶师小说 | 四虎免费在线观看 | 精品性影院一区二区三区内射 | 欧美日韩中文国产一区二区三区 | 我要色色网 | 我在厨房摸岳的乳HD在线观看 | 亚洲精品欧洲久久婷婷99 | 天美麻豆 | 农村老少伦小说 | 风间由美在线播放 | 国产高清日韩 | 禁忌第一季第3季 | 白丝打脚枪 | 97导航| 亚洲男人天堂网站 | 91日本在线 | ysl千人千色t9t9t9 | 四虎新网址 | caoporn超碰最新地址进入 | 精品成人在线 | 97se亚洲国产综合自在线观看 | 亚洲国产精品久久无套麻豆 | 精品亚洲视频在线 | 校花的第一次好紧好爽 | 日韩在线一区二区三区 | 国产自拍啪啪 | 国产精品区一区二区免费 | chinese456老人gay| 国产成人盗摄精品 | 秋霞理论一级在线观看手机版 | 色老板成人永久免费视频 | 天天干女人| 国产免费一区不卡在线 |