淺解前端必須掌握的算法(五):堆排序(上)

前言

雖然前端面試中不多會考到算法類的題目,可是你去好比像騰訊同樣的大廠面試的時候就知道了,對基本算法的掌握對於從事計算機科學技術的咱們來講,仍是必不可少的,天天花上 10 分鐘,輕鬆瞭解基本算法概念以及前端的實現方式。前端

另外,掌握了一些基本的算法實現,對於咱們平常開發來講,也是如虎添翼,能讓咱們的 js 業務邏輯更趨高效和流暢。面試

特別說明

今天這個算法稍微比較複雜,牽扯到的概念也比較多,須要先了解基礎知識。我給每篇文章的定位是 10 分鐘內應該要掌握下來,因此我就擅做主張地將堆排序算法講解分割爲上、下兩篇文章了,但願能讓你們閱讀起來更清爽愉快。算法

文章結構

《堆排序(上)》文章結構:數組

  • 簡單的二叉樹
  • 簡單的滿二叉樹
  • 簡單的徹底二叉樹
  • 簡單的堆
  • 簡單的堆分類

《堆排序(下)》文章結構:微信

  • 算法介紹
  • 輕鬆實現大頂堆調整
  • 輕鬆實現建立大頂堆
  • 輕鬆實現堆排序
  • 複雜度分析

簡單的二叉樹

要了解堆,必須先了解一下二叉樹,二者關係在下一步闡述。數據結構

二叉樹(Binary Tree)是每個節點最多有兩個分支的樹結構,一般分支被稱做「左子樹」和「右子樹」,分支具備左右次序,不能隨意顛倒。ui

二叉樹第 i 層最多擁有 2^(i-1) 個節點,深度爲 k 的二叉樹最多共有 2^(k+1)-1 個節點,且定義根節點所在的層級 i=0,所在的深度 k=0。注意該定義在全文起做用,後續不繼續說起。spa

二叉樹示意圖

二叉樹示意圖code

簡單的滿二叉樹

假設某個二叉樹深度爲 k,第 i 層擁有 2^(i-1) 個節點,且總共擁有 2^(k+1)-1 個節點,這樣的二叉樹稱爲「滿二叉樹」。cdn

換句話說,二叉樹的每一層都是滿的,除了最後一層上的節點,每個節點都具備左節點和右節點。

滿二叉樹示意圖

滿二叉樹示意圖

簡單的徹底二叉樹

假設某個二叉樹深度爲 k,共有 n 個節點,當且僅當其中的每個節點,均可以和一樣深度爲 k 的滿二叉樹上的,按層序編號相同的節點,也就是序號爲 1n 的節點,均一一對應時,這樣的二叉樹稱爲「徹底二叉樹」。

滿二叉樹必定是徹底二叉樹,可是徹底二叉樹不必定是滿二叉樹。

徹底二叉樹示意圖

徹底二叉樹示意圖

以下的就不是徹底二叉樹,樹 1 中 10 號節點缺失,樹 2 中 六、7 號節點缺失,樹 3 中 十、11 號節點缺失。

不是徹底二叉樹示意圖

不是徹底二叉樹示意圖

簡單的堆

堆(Heap),一類特殊的數據結構的統稱,一般是一個能夠被看作一棵樹的數組對象。

堆的實現經過構造二叉堆(binary heap),實爲二叉樹的一種,因爲其應用的廣泛性,當不加限定時,均指該數據結構的這種實現。

堆,是徹底二叉樹。

堆和數組相互關係示意圖

堆和數組相互關係示意圖

對於給定的某個節點的下標 idx,能夠很容易地計算出這個節點的父節點與孩子節點的下標:

// 計算父節點的下標
var getParentPos = function(idx){
  return Math.floor(idx / 2);
}

// 計算左子節點的下標
var getLeftChildPos = function(idx){
  return 2*idx;
};

// 計算右子節點的下標
var getRightChildPos = function(idx){
  return 2*idx + 1;
};
複製代碼

以下圖,取下標 idx = 4 的節點,則其父節點的下標就爲 Math.floor(4/2) === 2,其左子節點的下標就爲 2*4 === 8,其右子節點的下標就爲 2*4 + 1 === 9

計算親屬節點位置示意圖

計算親屬節點位置示意圖

但將堆轉換爲數組時,因爲數組的初始化下標始終爲 0,因此咱們的堆數據結構模型在此時要發生以下改變:

改變數據結構模型示意圖

改變數據結構模型示意圖

一樣的,以上的算法也須要作一下微調:

// 計算父節點的下標
var getParentPos = function(idx){
  return Math.floor((idx-1) / 2);
}

// 計算左子節點的下標
var getLeftChildPos = function(idx){
  return 2*idx + 1;
};

// 計算右子節點的下標
var getRightChildPos = function(idx){
  return 2 * (idx+1);
};
複製代碼

簡單的堆分類

二叉堆通常分爲兩種:「大頂堆」和「小頂堆」。

假設有一個堆,其中每一個節點的值都大於或等於其左右孩子節點的值,則該堆稱爲「大頂堆」。「大頂堆」的最大元素值出如今根節點。

大頂堆示意圖

大頂堆示意圖

假設有一個堆,其中每一個節點的值都小於或等於其左右孩子節點的值,則該堆稱爲「小頂堆」。「小頂堆」的最小元素值出如今根節點。

小頂堆示意圖

小頂堆示意圖

參考連接

bubkoo.com/2014/01/14/…

zh.wikipedia.org/wiki/%E5%A0…


微信公衆號 以爲本文不錯的話,分享一下給小夥伴吧~

相關文章
相關標籤/搜索