搜尋
首頁web前端js教程圖文詳解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 個節點稱為滿叉樹

201654180037749.png (325×199)

(深度為 3 的滿叉樹 full binary tree)
完全二元樹:深度為 k,有 n 個節點的二元樹,當且僅當其每一個節點都與深度為 k 的滿二叉樹中序號為 1 至 n 的節點對應時,稱之為完全二叉樹

201654180205013.png (298×198)

(深度為 3 的完全二元樹 complete binary tree)
2. 什麼是堆?
堆(二元堆)可以視為一棵完全的二元樹,完全二元樹的一個「優秀」的性質是,除了最底層之外,每一層都是滿的,這使得堆可以利用數組來表示(普通的一般的二元樹通常以鍊錶作為基本容器表示),每一個結點對應數組中的一個元素。
如下圖,是一個堆和數組的相互關係

201654180403849.png (564×182)

(堆和陣列的相互關係)
對於給定的某個結點的下標 i,可以很容易的計算出這個結點的父結點、孩子結點的下標:
Parent(i) = floor(i/2),i 的父節點下標
Left(i) = 2i,i 的左子節點下標
Right(i) = 2i + 1,i 的右子節點下標

201654180531505.png (549×172)

二元堆一般分為兩種:最大堆和最小堆。
最大堆:
最大堆中的最大元素值出現在根結點(堆頂)
堆中每個父節點的元素值都大於等於其孩子結點(如果存在)

201654180552874.png (373×112)

(最大堆)
最小堆:
最小堆中的最小元素值出現在根結點(堆頂)
堆中每個父節點的元素值都小於等於其孩子結點(如果存在)

201654180607921.png (370×112)

(最小堆)
3. 堆排序原理
堆排序就是把最大堆堆頂的最大數取出,將剩餘的堆繼續調整為最大堆,再次將堆頂的最大數取出,這個過程持續到剩餘數只有一個時結束。在堆中定義以下幾個操作:
最大堆調整(Max-Heapify):將堆的末端子節點作調整,使得子節點永遠小於父節點
建立最大堆(Build-Max-Heap):將堆所有資料重新排序,使其成為最大堆
堆排序(Heap-Sort):移除位元在第一個資料的根節點,並做最大堆調整的遞歸運算
在繼續進行下面的討論之前,需要注意的一個問題是:數組都是 Zero-Based,這意味著我們的堆資料結構模型要改變

201654180627211.png (562×194)

(Zero-Based)
對應的,幾個計算公式也要做出相應調整:
Parent(i) = floor((i-1)/2),i 的父節點下標
Left(i) = 2i + 1,i 的左子節點下標
Right(i) = 2(i + 1),i 的右子節點下標
最大堆調整(MAX‐HEAPIFY)的作用是保持最大堆的性質,是創建最大堆的核心子程序,作用過程如圖所示:

201654180644675.png (564×411)

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

一般的に、再帰は主に分割統治法で使用されますが、ここでは分割統治は必要ありません。さらに、再帰呼び出しではスタックのプッシュ/クリアが必要となるため、反復に比べてパフォーマンスが若干劣ります。もちろん、20/80 ルールに従って、これは無視できます。ただし、再帰を使用すると不快に感じる場合は、次のような反復を使用することもできます:

/**
 * 从 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;
}

最大ヒープを作成する機能 (Build-Max-Heap) は、配列を最大ヒープに変換することです。配列とヒープ サイズの 2 つのパラメーターを受け取ります。Build-Max-Heap は下から順に Max-Heapify を呼び出します。配列を変換し、最大のヒープを作成します。 Max-Heapify では、添え字 i を持つノード以降のノードが最大ヒープ プロパティを満たすことを保証できるため、ボトムアップで Max-Heapify を呼び出すことで、変換プロセス中にこのプロパティを維持できます。最大ヒープ内の要素の数が n の場合、Build-Max-Heap は Parent(n) から開始され、上向きに Max-Heapify を呼び出します。プロセスは次のとおりです:


201654180758506.jpg (614×673)

JavaScriptでは次のように記述します。

function buildMaxHeap(array, heapSize) {
 var i,
   iParent = Math.floor((heapSize - 1) / 2);
   
 for (i = iParent; i >= 0; i--) {
  maxHeapify(array, i, heapSize);
 }
}
Heap-Sort は、ヒープ ソートのインターフェイス アルゴリズムです。Heap-Sort は、まず Build-Max-Heap を呼び出して配列を最大ヒープに変換し、次にヒープの上部と下部の要素を交換し、次に下部を引き上げます。最後に Max-Heapify を呼び出して、最大ヒープ プロパティを維持します。ヒープの先頭要素はヒープ内で最大の要素でなければならないため、1回の操作の後、ヒープ内に存在する最大の要素をヒープから切り離し、n-1回繰り返した後、配列を配置します。全体のプロセスは次のとおりです:


201654180823776.jpg (604×926)

JavaScriptでは次のように記述します。

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 個の最大数」などの問題を解く場合、ほぼ推奨されるアルゴリズムです。

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
從C/C到JavaScript:所有工作方式從C/C到JavaScript:所有工作方式Apr 14, 2025 am 12:05 AM

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript引擎:比較實施JavaScript引擎:比較實施Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

超越瀏覽器:現實世界中的JavaScript超越瀏覽器:現實世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

使用Next.js(後端集成)構建多租戶SaaS應用程序使用Next.js(後端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

如何使用Next.js(前端集成)構建多租戶SaaS應用程序如何使用Next.js(前端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:22 AM

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

JavaScript:探索網絡語言的多功能性JavaScript:探索網絡語言的多功能性Apr 11, 2025 am 12:01 AM

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

JavaScript的演變:當前的趨勢和未來前景JavaScript的演變:當前的趨勢和未來前景Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

神秘的JavaScript:它的作用以及為什麼重要神秘的JavaScript:它的作用以及為什麼重要Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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