<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [toc] # 介紹 堆(Heap)是一種特殊的二叉樹: 1. 堆是一個完全二叉樹 2. 堆中每一個節點的值都必須大于等于(或小于等于)其子樹中的每個節點的值 # 分類 堆分為兩種:`大頂堆` 和 `小頂堆` 。 * 大頂堆:父頂點的值大于所有子頂點的值。 * 小頂堆:父頂點的值小于所有子頂點的值。 大頂堆: ![](https://img.kancloud.cn/bc/58/bc585c066f684abfc06cbd52c0c23199_410x304.png) 小頂堆: ![](https://img.kancloud.cn/92/ca/92caa577acc264a09aaf7b9b2eebb6b1_900x458.png) # 存儲 堆是一種二叉樹,有兩種存儲方式: - 數組 - 鏈表 堆是一種完全二叉樹,而完全二叉樹使用 `數組` 存儲比較合適。 ![](https://img.kancloud.cn/36/7c/367c25251bdf4400bc285f53280b1b6e_1166x814.png) 當以數組保存二叉樹時有以下幾個重要公式。 1. 對于下標為 i 節點(子節點) 左子節點下標:2i+1 右子節點下標:2i+2 2. 對于下標為 i 的節點(父節點) 父節點下標:Math.floor( (i-1) / 2 ) 3. 最后一個非葉子節點的節點的下標 Math.floor(len/2) - 1 # 應用場景 1. 排序 ---》 堆排序(時間復雜度:O(nlogn) 2. 優先隊列(優先級高的放到前面) # 操作 二叉堆的操作有三種: - 插入節點 - 刪除節點 - 構建二叉堆 ## 插入節點 當向二叉堆中插入新節點時的操作: 1. 將新節點先放到 `最后` 2. 然后依次和父節點比較,然后 `上浮` 如,插入0: 1. 插入到最后 ![](https://img.kancloud.cn/da/ae/daae5dae58bef0c312127a568b94839e_1130x908.png) 2. 和父節點比較并上浮 ![](https://img.kancloud.cn/a8/8d/a88d3375ffc71bf7f3fd5c48355132ae_1128x884.png) 3. 和父節點比較并上浮 ![](https://img.kancloud.cn/26/70/267076bba73a892c7b439f3cc68999a0_1152x890.png) 4. 繼續比較上浮 ![](https://img.kancloud.cn/2e/51/2e51c02ed76614e2f7b1d980e87f8ea1_1140x910.png) ## 刪除節點 刪除節點時,一般就是刪除堆是根節點,過程和插入節點正好相反: 1. 刪除頂節點 2. 將最后一個節點拿到父節點 3. 和子節點比較并 `下沉` 比如,刪除 1 1. 刪除節點 ![](https://img.kancloud.cn/c3/97/c397773fae8ae6618c2a2561d9a8b5fa_1158x920.png) 2. 將最后一個節點臨時拿到根節點的位置 ![](https://img.kancloud.cn/7e/63/7e630a205fd7f2959c96463df649ba0b_1132x920.png) 3. 和左右子節點比較,讓最小的節點上來,它下沉 ![](https://img.kancloud.cn/45/3d/453d39201ebdeba182ad959a96f15b1d_1130x910.png) 4. 繼續和子節點比較并下沉 ![](https://img.kancloud.cn/b4/5b/b45b447cca54c4bc43768f69f2d3a477_1118x924.png) ## 構建二叉堆 [排序](%E6%8E%92%E5%BA%8F.md)從最后一個 `非葉子節點 Math.floor(數組長度/2)-1` 開始比較并 (大/小)上浮。 1. 比較有以下堆 ![](https://img.kancloud.cn/fb/f3/fbf30d7369b90d7b8e9a18825f040c8c_752x650.png) 2. 從最后一個非葉子節點開始比較 ![](https://img.kancloud.cn/1f/f4/1ff49256e83091bf1a7b69b6d01b0fd6_830x330.png) ![](https://img.kancloud.cn/b2/b1/b2b1d2417381cecbc1a5e4f3cdcc55a1_1022x814.png) # 代碼實現 ~~~ // 小頂堆 class SmallHeap { constructor() { // 初始化一個保存數據的數組 this.arr = [] } // 向堆中放數據 push(data) { // 1. 先將數據放到堆尾 this.arr.push(data) // 2. 上浮(依次和父節點進行比較) // 2.1 獲取當前這個新元素的下標 let current = this.arr.length - 1 // 2.2 父元素的下標 let parent = Math.floor((current - 1) / 2) // 2.3 循環一直找父節點 while (parent >= 0) { // 2.4 和父節點比較 if (this.arr[current] < this.arr[parent]) { // 2.5 交換 [this.arr[current], this.arr[parent]] = [this.arr[parent], this.arr[current]] // 2.6 當前節點的下標變成父節點的下標 current = parent // 2.7 重新計算新的父節點 parent = Math.floor((current - 1) / 2) } else { // 2.8 如果當前節點大就退出循環 break } } } // 彈出堆頂元素 pop() { // 1. 獲取堆頂元素的值 let value = this.arr[0] // 2. 獲取數組中最后一個元素的值,并將這個值從數組中刪除 let lastValue = this.arr.pop() // 3. 最后一個值替換第1個元素 this.arr[0] = lastValue // 4. 和子節點比較然后進行下沉 // 4.1 當前節點的下標 let current = 0 // 4.2 左、右子節點的下標 let left = 2 * current + 1 let right = 2 * current + 2 let smallest = 0 // 最小元素的下標 // 如果有子節點就向下比較 while (left < this.arr.length) { // 4.3 比左子節點大 if (this.arr[current] > this.arr[left]) { // 左子節點和右子節點的大小 if (this.arr[left] > this.arr[right]) { // 右邊最小 smallest = right } else { // 左邊最小 smallest = left } } else { // 當前節點小于左子節點 // 判斷和右子節點的大小 if (this.arr[current] <= this.arr[right]) { // 退出循環 break } else { smallest = right } } // 最小元素的下標和當前元素下標是否相等 if (current === smallest) { break } else { // 當前元素和最小元素進行交換 [this.arr[current], this.arr[smallest]] = [this.arr[smallest], this.arr[current]] // 修改相關下標 current = smallest // 當前下標變成交換之后最小的下標 // 重新計算左右子節點下標 left = 2 * current + 1 right = 2 * current + 2 } } return value } } let smH = new SmallHeap() smH.push(10) smH.push(5) smH.push(2) smH.push(8) smH.push(1) smH.push(4) console.log(smH.arr) console.log(smH.pop()) console.log(smH.arr) ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看