国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java堆排序算法詳解

Java堆排序算法詳解

2021-01-13 14:47Amedeo Java教程

這篇文章主要為大家詳細介紹了Java堆排序算法的相關代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下

堆是數據結構中的一種重要結構,了解“堆”的概念和操作,可以幫助我們快速地掌握堆排序。

堆的概念

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

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

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

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

堆的建立和維護

堆可以支持多種操作,但現在我們關心的只有兩個問題:

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

2.刪除堆頂元素后,如何調整數組成為新堆?

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

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

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

我看過的數據結構的書很多都是從第一個非葉子結點向下篩選,直到根元素篩選完畢。這個方法叫“篩選法”,需要循環篩選n/2個元素。

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

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

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

算法概述/思路

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

?
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
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;
  }
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://www.cnblogs.com/Amedeo/p/6138674.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 性欧美大战久久久久久久免费观看 | 亚洲人人| 日日夜夜精品免费视频 | 国产1级片 | 日本视频二区 | 午夜午夜精品一区二区三区文 | 日韩精品免费在线观看 | 综合久久综合 | 伊人久久一区 | 超级黄色毛片 | 欧美日韩精品久久久 | 久久99视频精品 | 日韩城人网站 | 日韩精品在线一区二区 | 免费裸体无遮挡黄网站免费看 | 免费成人在线网站 | 成人1区 | 日韩电影免费在线观看中文字幕 | 亚洲欧洲在线观看 | 亚洲成人精品在线观看 | 国产精品久久国产精品 | 亚洲国产aⅴ成人精品无吗 成人午夜视频在线观看 | av网站在线免费观看 | 亚洲成人高清在线 | 亚洲国产视频网 | 日韩精品一区二区三区视频播放 | 欧美黄视频 | 久草av在线播放 | eeuss国产一区二区三区四区 | 青青草原综合久久大伊人精品 | 探花av在线 | 凹凸国产成人精品视频免费 | 国产三级 | 欧美国产日韩一区二区三区 | 欧美日韩精品免费观看 | 人人爱超碰 | 欧美精品一区二区三区一线天视频 | 91精品国产综合久久久久久丝袜 | 久久专区 | www亚洲精品| 国产精品一二区 |