中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

堆排序的實現原理是什么

發布時間:2020-11-24 16:47:16 來源:億速云 閱讀:106 作者:Leah 欄目:編程語言

本篇文章給大家分享的是有關堆排序的實現原理是什么,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

對于堆排序會涉及一些完全二叉樹知識。對于待排序列{10, 2, 11, 8, 7},把它看成是一顆完全二叉樹,如下圖所示。

堆排序的實現原理是什么

堆分為大根堆和小根堆:大根堆表示每個根節點均大于其子節點(L(i) >= L(2i) && L(i) >= L(2i + 1)),小根堆表示每個根節點均小于其子節點(L(i) <= L(2i) && L(i) <= L(2i + 1))。(在完全二叉樹中第i個節點的左子節點為2i,其右字節點為2i + 1

本文將以大根堆的構建作為示例進行講解。

堆排序的第一步——構建初始堆。如何構建初始堆呢?根據定義,關鍵點在于每個根節點。觀察上述待排序列的完全二叉樹,不難發現存在節點2和節點10有子節點,它們是需要關注的節點。

堆排序的實現原理是什么

如何定位節點2呢?發現它是葉子節點,或者最后一個節點的父節點,根據完全二叉樹的性質可知,除根節點外任意節點的父節點的編號為&#8970;n / 2&#8971;。已知n = 5,易知節點2的編號為&#8970;5 / 2&#8971; = ②。比較它與左右子節點的大小并調整。

堆排序的實現原理是什么

最后剩下根節點10,已知節點2的編號為② - 1 = ①即得到根節點10的編號。比較它與左右子節點的大小并調整。

堆排序的實現原理是什么

調整完畢后發現已經構成了一個大根堆,示例中的待排序列較為簡單,再給出一個較為復雜的待排序列,觀察其構建大根堆的過程。對于待排序列{53, 17, 78, 09, 45, 65, 87, 32},將它看成一顆完全二叉樹。

堆排序的實現原理是什么

同樣我們來看它所需要關注的節點有哪些。

堆排序的實現原理是什么

根據第一個例子,我們很容易能定位節點09的編號為&#8970;8 / 2&#8971; = ④,節點78的編號為④ - 1 = ③……,依次類推,發現了一定的規律,即需要調整的節點位置從&#8970;n / 2&#8971;開始依次遞減直到根節點結束(&#8970;n / 2&#8971; ~ 1)。現在開始調整。

堆排序的實現原理是什么

堆排序的實現原理是什么

堆排序的實現原理是什么

堆排序的實現原理是什么

在第四次調整結束后發現節點53不滿足大根堆的定義,其右子節點大于它,此時需要做進一步的向下調整。

堆排序的實現原理是什么

注意向下調整是每次向上調整的時候都需要做的判斷是否需要向下調整,而不是在所有的向上調整結束過后再回過頭來向下調整。這樣大根堆就建立好了,此時待排序列數組情況已經發生了改變:{87, 45, 78, 32, 17, 65, 53, 09}。接下來是如何進行排序的問題。將大根堆的根節點與最后一個節點互換,并調整二叉樹使其仍然滿足大根堆。

堆排序的實現原理是什么

可以看到將根節點與最后一個節點呼喚后,待排序列的最大值已經放到了數組的最后一個位置{……, 87},此時完成了第一趟排序,但這第一趟排序還沒有結束,此時除節點87外,其余節點并不滿足大根堆的條件,所以需要對其余節點進行調整為大根堆。排序過程不再給出,JavaPython3的代碼實現如下。

Java

package com.algorithm.sort.heap;

import java.util.Arrays;

/**
 * 堆排序
 * Created by yulinfeng on 6/20/17.
 */
public class Heap {
  
  public static void main(String[] args) {
    int[] nums = {53, 17, 78, 09, 45, 65, 87, 32};
    nums = heapSort(nums);
    System.out.println(Arrays.toString(nums));
  }
  
  /**
   * 堆排序
   * @param nums 待排序數組序列
   * @return 排好序的數組序列
   */
  private static int[] heapSort(int[] nums) {
  
    for (int i = nums.length / 2 - 1; i >= 0; i--) {
      heapAdjust(nums, i, nums.length);
    }
    for (int i = nums.length - 1; i > 0; i--) {
      int temp = nums[i];
      nums[i] = nums[0];
      nums[0] = temp;
      heapAdjust(nums, 0, i);
    }
    return nums;
  }
  
  /**
   * 調整堆
   *
   * @param nums  待排序序列
   * @param parent   待調整根節點
   * @param length 數組序列長度
   */
  private static void heapAdjust(int[] nums, int parent, int length) {
    int temp = nums[parent];
    int childIndex = 2 * parent + 1;  //完全二叉樹節點i從編號1開始的左子節點位置在2i,此處數組下標從0開始,即左子節點所在數組索引位置為:2i + 1
    while (childIndex < length) {
      if (childIndex + 1 < length && nums[childIndex] < nums[childIndex + 1]) {
        childIndex++;  //節點有右子節點,且右子節點大于左子節點,則選取右子節點
      }
      if (temp > nums[childIndex]) {
        break; //如果選中節點大于其子節點,直接返回
      }
      nums[parent] = nums[childIndex];
      parent = childIndex;
      childIndex = 2 * parent + 1;  //繼續向下調整
    }
    nums[parent] = temp;
  }
}

Python3

#堆排序
def heap_sort(nums):

  for i in range(int(len(nums) / 2 - 1), -1, -1):
    heap_adjust(nums, i, len(nums))
  
  for i in range(len(nums) - 1, -1, -1):
    temp = nums[i]
    nums[i] = nums[0]
    nums[0] = temp
    heap_adjust(nums, 0, i)
  
  return nums

#調整堆
def heap_adjust(nums, parent, length):
  
  temp = nums[parent]
  childIndex = 2 * parent + 1
  while childIndex < length:
    if childIndex + 1 < length and nums[childIndex] < nums[childIndex + 1]:
      childIndex += 1
    if temp > nums[childIndex]:
      break
    nums[parent] = nums[childIndex]
    parent = childIndex
    childIndex = 2 * parent + 1
  
  nums[parent] = temp
    
nums = [53, 17, 78, 09, 45, 65, 87, 32]
nums = heap_sort(nums)
print(nums)

以上就是堆排序的實現原理是什么,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

大连市| 平山县| 鄂温| 博爱县| 聂拉木县| 饶平县| 凤冈县| 板桥市| 镇康县| 柞水县| 马公市| 科技| 顺昌县| 稻城县| 龙州县| 绵阳市| 子洲县| 叶城县| 时尚| 陆良县| 六安市| 西安市| 乐业县| 罗江县| 马公市| 呼伦贝尔市| 西贡区| 饶河县| 新竹市| 光山县| 阳谷县| 黔西| 义马市| 永年县| 建宁县| 朝阳市| 夹江县| 迁安市| 连江县| 峨眉山市| 博野县|