圖文詳解Heap Sort堆排序演算法及JavaScript的程式碼實作_基礎知識
1. 不得不說說二元樹
要了解堆首先得了解二叉樹,在電腦科學中,二元樹是每個節點最多有兩個子樹的樹結構。通常子樹被稱為「左子樹」(left subtree)和「右子樹」(right subtree)。二元樹常被用來實現二元查找樹和二元堆。
二元樹的每個結點至多只有二棵子樹(不存在度大於 2 的結點),二叉樹的子樹有左右之分,次序不能顛倒。二元樹的第i 層至多有2i - 1 個結點;深度為k 的二元樹至多有2k - 1 個結點;對任何一棵二元樹T,如果其終端結點數為n0,度為2 的結點數為n2,則n0 = n2 + 1。
樹和二元樹的三個主要差異:
樹的結點個數至少為 1,而二元樹的結點數量可以是 0
樹中結點的最大度數沒有限制,而二元樹結點的最大度數為 2
樹的結點無左、右之分,而二元樹的結點有左、右之分
二元樹又分為完全二元樹(complete binary tree)和滿二元樹(full binary tree)
滿叉樹:一棵深度為 k,且有 2k - 1 個節點稱為滿叉樹
(深度為 3 的滿叉樹 full binary tree)
完全二元樹:深度為 k,有 n 個節點的二元樹,當且僅當其每一個節點都與深度為 k 的滿二叉樹中序號為 1 至 n 的節點對應時,稱之為完全二叉樹
(深度為 3 的完全二元樹 complete binary tree)
2. 什麼是堆?
堆(二元堆)可以視為一棵完全的二元樹,完全二元樹的一個「優秀」的性質是,除了最底層之外,每一層都是滿的,這使得堆可以利用數組來表示(普通的一般的二元樹通常以鍊錶作為基本容器表示),每一個結點對應數組中的一個元素。
如下圖,是一個堆和數組的相互關係
(堆和陣列的相互關係)
對於給定的某個結點的下標 i,可以很容易的計算出這個結點的父結點、孩子結點的下標:
Parent(i) = floor(i/2),i 的父節點下標
Left(i) = 2i,i 的左子節點下標
Right(i) = 2i + 1,i 的右子節點下標
二元堆一般分為兩種:最大堆和最小堆。
最大堆:
最大堆中的最大元素值出現在根結點(堆頂)
堆中每個父節點的元素值都大於等於其孩子結點(如果存在)
(最大堆)
最小堆:
最小堆中的最小元素值出現在根結點(堆頂)
堆中每個父節點的元素值都小於等於其孩子結點(如果存在)
(最小堆)
3. 堆排序原理
堆排序就是把最大堆堆頂的最大數取出,將剩餘的堆繼續調整為最大堆,再次將堆頂的最大數取出,這個過程持續到剩餘數只有一個時結束。在堆中定義以下幾個操作:
最大堆調整(Max-Heapify):將堆的末端子節點作調整,使得子節點永遠小於父節點
建立最大堆(Build-Max-Heap):將堆所有資料重新排序,使其成為最大堆
堆排序(Heap-Sort):移除位元在第一個資料的根節點,並做最大堆調整的遞歸運算
在繼續進行下面的討論之前,需要注意的一個問題是:數組都是 Zero-Based,這意味著我們的堆資料結構模型要改變
(Zero-Based)
對應的,幾個計算公式也要做出相應調整:
Parent(i) = floor((i-1)/2),i 的父節點下標
Left(i) = 2i + 1,i 的左子節點下標
Right(i) = 2(i + 1),i 的右子節點下標
最大堆調整(MAX‐HEAPIFY)的作用是保持最大堆的性質,是創建最大堆的核心子程序,作用過程如圖所示:
(Max-Heapify)
1 回の調整後もヒープはヒープ プロパティに違反しているため、ヒープ全体がヒープ プロパティを満たすようにするために再帰的テストが必要です。これは JavaScript で次のように表現できます。
/** * 从 index 开始检查并保持最大堆性质 * * @array * * @index 检查的起始下标 * * @heapSize 堆大小 * **/ function maxHeapify(array, index, heapSize) { var iMax = index, iLeft = 2 * index + 1, iRight = 2 * (index + 1); if (iLeft < heapSize && array[index] < array[iLeft]) { iMax = iLeft; } if (iRight < heapSize && array[iMax] < array[iRight]) { iMax = iRight; } if (iMax != index) { swap(array, iMax, index); maxHeapify(array, iMax, heapSize); // 递归调整 } } function swap(array, i, j) { var temp = array[i]; array[i] = array[j]; array[j] = temp; }
/** * 从 index 开始检查并保持最大堆性质 * * @array * * @index 检查的起始下标 * * @heapSize 堆大小 * **/ function maxHeapify(array, index, heapSize) { var iMax, iLeft, iRight; while (true) { iMax = index; iLeft = 2 * index + 1; iRight = 2 * (index + 1); if (iLeft < heapSize && array[index] < array[iLeft]) { iMax = iLeft; } if (iRight < heapSize && array[iMax] < array[iRight]) { iMax = iRight; } if (iMax != index) { swap(array, iMax, index); index = iMax; } else { break; } } } function swap(array, i, j) { var temp = array[i]; array[i] = array[j]; array[j] = temp; }
function buildMaxHeap(array, heapSize) { var i, iParent = Math.floor((heapSize - 1) / 2); for (i = iParent; i >= 0; i--) { maxHeapify(array, i, heapSize); } }
function heapSort(array, heapSize) { buildMaxHeap(array, heapSize); for (int i = heapSize - 1; i > 0; i--) { swap(array, 0, i); maxHeapify(array, 0, i); } }
4.JavaScript 言語の実装
最後に、上記を次のように完全な JavaScript コードにまとめます。
function heapSort(array) { function swap(array, i, j) { var temp = array[i]; array[i] = array[j]; array[j] = temp; } function maxHeapify(array, index, heapSize) { var iMax, iLeft, iRight; while (true) { iMax = index; iLeft = 2 * index + 1; iRight = 2 * (index + 1); if (iLeft < heapSize && array[index] < array[iLeft]) { iMax = iLeft; } if (iRight < heapSize && array[iMax] < array[iRight]) { iMax = iRight; } if (iMax != index) { swap(array, iMax, index); index = iMax; } else { break; } } } function buildMaxHeap(array) { var i, iParent = Math.floor(array.length / 2) - 1; for (i = iParent; i >= 0; i--) { maxHeapify(array, i, array.length); } } function sort(array) { buildMaxHeap(array); for (var i = array.length - 1; i > 0; i--) { swap(array, 0, i); maxHeapify(array, 0, i); } return array; } return sort(array); }
5. ヒープソートアルゴリズムの適用
(1) アルゴリズムのパフォーマンス/複雑さ
ヒープソートの時間計算量は非常に安定しており (入力データの影響を受けないことがわかります)、最良の場合でも最悪の場合でも O(n㏒n) の計算量です。
ただし、その空間の複雑さは実装ごとに異なります。 2 つの一般的な複雑さ、O(n) と O(1) については上で説明しました。スペースを節約するという原則に従って、O(1) 複雑さの方法をお勧めします。
(2) アルゴリズムの安定性
ヒープソートには多数のスクリーニングと移動プロセスが含まれ、不安定なソートアルゴリズムです。
(3) アルゴリズム適用シナリオ
ヒープのソートは、ヒープの確立と調整のプロセスで比較的大きなオーバーヘッドを引き起こすため、要素が少ない場合には適していません。ただし、要素がたくさんある場合には、それでも良い選択です。特に、「最初の n 個の最大数」などの問題を解く場合、ほぼ推奨されるアルゴリズムです。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

人臉偵測辨識技術已經是一個比較成熟且應用廣泛的技術。而目前最廣泛的網路應用語言非JS莫屬,在Web前端實現人臉偵測辨識相比後端的人臉辨識有優勢也有弱勢。優點包括減少網路互動、即時識別,大大縮短了使用者等待時間,提高了使用者體驗;弱勢是:受到模型大小限制,其中準確率也有限。如何在web端使用js實現人臉偵測呢?為了實現Web端人臉識別,需要熟悉相關的程式語言和技術,如JavaScript、HTML、CSS、WebRTC等。同時也需要掌握相關的電腦視覺和人工智慧技術。值得注意的是,由於Web端的計

股票分析必備工具:學習PHP和JS繪製蠟燭圖的步驟,需要具體程式碼範例隨著網路和科技的快速發展,股票交易已成為許多投資者的重要途徑之一。而股票分析是投資人決策的重要一環,其中蠟燭圖被廣泛應用於技術分析。學習如何使用PHP和JS繪製蠟燭圖將為投資者提供更多直觀的信息,幫助他們更好地做出決策。蠟燭圖是一種以蠟燭形狀來展示股票價格的技術圖表。它展示了股票價格的

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

隨著網路金融的快速發展,股票投資已經成為了越來越多人的選擇。而在股票交易中,蠟燭圖是常用的技術分析方法,它能夠顯示股票價格的變動趨勢,幫助投資人做出更精準的決策。本文將透過介紹PHP和JS的開發技巧,帶領讀者了解如何繪製股票蠟燭圖,並提供具體的程式碼範例。一、了解股票蠟燭圖在介紹如何繪製股票蠟燭圖之前,我們首先需要先了解什麼是蠟燭圖。蠟燭圖是由日本人

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest
