首頁 web前端 js教程 JS實作紅黑樹步驟詳解

JS實作紅黑樹步驟詳解

May 08, 2018 pm 02:54 PM
javascript 步驟 詳解

這次帶給大家JS實現紅黑樹步驟詳解,JS實現紅黑樹的注意事項有哪些,下面就是實戰案例,一起來看一下。

紅黑樹的性質

一棵滿足以下性質的二元搜尋樹是一棵紅黑樹

  1. #每個結點或是黑色或是紅色。

  2. 根結點是黑色的。

  3. 每個葉結點(NIL)是黑色的。

  4. 如果一個結點是紅色的,則它的兩個子結點都是黑色的。

  5. 對每個結點,從該結點到其所有後代葉結點的簡單路徑上,均包含相同數目的黑色結點。

性質1和性質2,不用做太多解釋。

性質3,每個葉結點(NIL)是黑色的。這裡的葉結點並不是指上圖結點1,5,8,15,而是指下圖中值為null的結點,它們的顏色為黑色,且是它們父結點的子結點。

性質4,如果一個結點是紅色的(圖中用白色代替紅色),則它的兩個子結點都是黑色的,例如結點2 ,5,8,15。但是,如果某結點的兩個子結點都是黑色的,則該結點未必是紅色的,例如結點1。

性質5,對每個結點,從該結點到其所有後代葉結點的簡單路徑上,均包含相同數目的黑色結點。例如,從結點2到其所有後代葉結點的簡單路徑上,黑色結點的數量都為2;從根結點11到其所有後代葉結點的簡單路徑上,黑色結點的數量都為3。

這樣的一棵樹有什麼特色呢?

透過對任何一條從根到葉結點的簡單路徑上各個結點的顏色進行約束,紅黑樹確保沒有一條路徑會比其他路徑長出2倍,因為是近似平衡的。 ——《演算法導論》

由於性質4,紅黑樹中不會出現兩個紅色結點相鄰的情形。樹中最短的可能出現的路徑是都是黑色結點的路徑,樹中最長的可能出現的路徑是紅色結點和黑色結點交替的路徑。再結合性質5,每條路徑上均包含相同數目的黑色結點,所以紅黑樹確保沒有一條路徑會比其他路徑長出2倍。

紅黑樹的插入

首先以二元搜尋樹的方式插入結點,並將其著為紅色。如果著為黑色,則會違反性質5,不便調整;如果著為紅色,可能會違背性質2或性質4,可以透過相對簡單的操作,使其恢復紅黑樹的性質。

一個結點以二元搜尋樹的方式被插入後,可能出現以下幾種情況:

情形1

##插入結點後,無父結點,結點插入成為根結點,違反性質2,將結點調整為黑色,完成插入。

情形2

插入結點後,其父結點為黑色,沒有違背任何性質,不用調整,完成插入。例如下圖中插入結點13。

情形3

在插入結點後,其父結點為紅色,違背了性質4,需要採取一系列的調整。例如下圖中插入結點4。

那麼一系列的調整是什麼呢?

如果插入結點node的父結點father為紅色,則結點father必然存在黑色的父結點grandfather,因為如果結點father不存在父結點的話,就是根結點,而根結點是黑色的。那麼結點grandfather的另一個子結點,我們可以稱為結點uncle,即結點father的兄弟結點。結點uncle可能為黑色,也可能為紅色。

先從最簡單的情形分析,因為複雜的情形可以轉換成簡單的情形,簡單的情形就是結點uncle為黑色的情形。

情形3.1

如上圖(a)中,情形是這樣的,node 為紅,father 為紅,grandfather 和uncle 為黑,α ,β,θ,ω,η 都是結點對應的子樹。假設整棵二元搜尋樹中,只有node和father因違反性質4而無法成為正常的紅黑樹,此時將圖(a)調整成圖(b),則可以恢復成正常的紅黑樹。整個調整過程中實際分為兩步,旋轉和變色。

什麼是旋轉?

如上圖(c)是一棵二元搜尋樹的一部分,其中x, y 是結點,α,β,θ 是對應結點的子樹。由圖可知,α < x < β < y < θ ,即α子樹中的所有結點都小於x,結點x都小於β子樹中的所有結點,β子樹中的所有結點的值都小於結點y 的值,結點y 的值都小於θ子樹中的所有結點。在二元搜尋樹中,如果結點y的值比結點x的值大,那麼結點x在結點y的左子樹中,如圖(c);或結點y在結點x的右子樹中,如圖(d)。故 α < x < β < y < θ ,也可以用圖(d)的結構來表現。這就是旋轉,它不會破壞二元搜尋樹的性質。

node 為紅,father 為紅,grandfather 和uncle 為黑的具體情形一

圖(a)中,node 為father 的左子結點, father 為grand 的左子結點,node < father < θ < grand < uncle。這種情形中father < grand,即可以表現為father 是grand 的左子樹,也可以表現為grand 是father 的右子樹,故將圖(a)中father 和grand 旋轉,旋轉雖然不會破壞二元搜尋樹的性質,但是旋轉之後,會破壞紅黑樹的性質,所以還需要調整結點的顏色。

變色

所以圖(a)旋轉過後,還要將 grand 變成紅色,father 變成黑色,變成圖(b),完成插入。

node 為紅,father 為紅,grandfather 和uncle 為黑的具體情形二

node 為father 的右子結點, father 為grand 的右子結點,如下圖( e),就是具體情形一的翻轉。

即,uncle < grand < θ < father < node ,將圖(e)father 和grand 旋轉,變色後,變成圖(f ),完成插入。

node 為紅,father 為紅,grandfather 和uncle 為黑的具體情形三

node 為father 的右子結點, father 為grand 的左子結點,如下圖( m)。

將圖(m)中node 和father 旋轉後,變成圖(n),將father看作新的node,就成為了具體情形一,再次旋轉,變色後,完成插入。

node 為紅,father 為紅,grandfather 和uncle 為黑的具體情形四

node 為father 的右子結點, father 為grand 的左子結點,如下圖( i),就是具體情形三的翻轉。

將圖(i)中node 和father 旋轉後,變成圖(j),將father看作新的node,就成為了具體情形二,再次旋轉,變色後,完成插入。

情形3.2

node ,father 和 uncle 為紅,grandfather 為黑。

如上圖(k),不旋轉,而是將grand著紅,father和uncle著黑,同時將grand當作新的node,進行情形的判斷。如果grand作為新的node後,變成了情形2,則插入完成;如果變成了情形3.1,則調整後,插入完成;如果仍是情形3.2,則繼續將grand,father和uncle變色,和node結點上移,如果新的node結點沒有父節點了,則變成了情形1,將根結點著為黑色,那麼插入完成。

綜上

##操作情形1node為紅,無father將node重新著色情形2node為紅,father為黑情形3.1node,father為紅,grand,uncle為黑旋轉一次或兩次,並重新著色情形3.2node,father,uncle為紅,grand為黑將father, uncle,grand重新著色, grand作為新的node
node的情形
代碼

// 结点
function Node(value) {
 this.value = value
 this.color = 'red' // 结点的颜色默认为红色
 this.parent = null
 this.left = null
 this.right = null
}
function RedBlackTree() {
 this.root = null
}
RedBlackTree.prototype.insert = function (node) {
 // 以二叉搜索树的方式插入结点
 // 如果根结点不存在,则结点作为根结点
 // 如果结点的值小于node,且结点的右子结点不存在,跳出循环
 // 如果结点的值大于等于node,且结点的左子结点不存在,跳出循环
 if (!this.root) {
 this.root = node
 } else {
 let current = this.root
 while (current[node.value <= current.value ? 'left' : 'right']) {
  current = current[node.value <= current.value ? 'left' : 'right']
 }
 current[node.value <= current.value ? 'left' : 'right'] = node
 node.parent = current
 }
 // 判断情形
 this._fixTree(node)
 return this
}
RedBlackTree.prototype._fixTree = function (node) {
 // 当node.parent不存在时,即为情形1,跳出循环
 // 当node.parent.color === 'black'时,即为情形2,跳出循环
 while (node.parent && node.parent.color !== 'black') {
 // 情形3
 let father = node.parent
 let grand = father.parent
 let uncle = grand[grand.left === father ? 'right' : 'left']
 if (!uncle || uncle.color === 'black') {
  // 叶结点也是黑色的
  // 情形3.1
  let directionFromFatherToNode = father.left === node ? 'left' : 'right'
  let directionFromGrandToFather = grand.left === father ? 'left' : 'right'
  if (directionFromFatherToNode === directionFromGrandToFather) {
  // 具体情形一或二
  // 旋转
  this._rotate(father)
  // 变色
  father.color = 'black'
  grand.color = 'red'
  } else {
  // 具体情形三或四
  // 旋转
  this._rotate(node)
  this._rotate(node)
  // 变色
  node.color = 'black'
  grand.color = 'red'
  }
  break // 完成插入,跳出循环
 } else {
  // 情形3.2
  // 变色
  grand.color = 'red'
  father.color = 'black'
  uncle.color = 'black'
  // 将grand设为新的node
  node = grand
 }
 }
 if (!node.parent) {
 // 如果是情形1
 node.color = 'black'
 this.root = node
 }
}
RedBlackTree.prototype._rotate = function (node) {
 // 旋转 node 和 node.parent
 let y = node.parent
 if (y.right === node) {
 if (y.parent) {
  y.parent[y.parent.left === y ? 'left' : 'right'] = node
 }
 node.parent = y.parent
 if (node.left) {
  node.left.parent = y
 }
 y.right = node.left
 node.left = y
 y.parent = node
 } else {
 if (y.parent) {
  y.parent[y.parent.left === y ? 'left' : 'right'] = node
 }
 node.parent = y.parent
 if (node.right) {
  node.right.parent = y
 }
 y.left = node.right
 node.right = y
 y.parent = node
 }
}
let arr = [11, 2, 14, 1, 7, 15, 5, 8, 4, 16]
let tree = new RedBlackTree()
arr.forEach(i => tree.insert(new Node(i)))
debugger

相信看了本文案例你已經掌握了方法,更多精彩請關注php中文網其它相關文章!

推薦閱讀:

js對數值數組進行去重與最佳化

Vue全域引入bass.scss步驟詳解
#

以上是JS實作紅黑樹步驟詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

熱門話題

Java教學
1665
14
CakePHP 教程
1424
52
Laravel 教程
1322
25
PHP教程
1270
29
C# 教程
1249
24
如何在iPhone中使Google地圖成為預設地圖 如何在iPhone中使Google地圖成為預設地圖 Apr 17, 2024 pm 07:34 PM

iPhone上的預設地圖是Apple專有的地理位置供應商「地圖」。儘管地圖越來越好,但它在美國以外的地區運作不佳。與谷歌地圖相比,它沒有什麼可提供的。在本文中,我們討論了使用Google地圖成為iPhone上的預設地圖的可行性步驟。如何在iPhone中使Google地圖成為預設地圖將Google地圖設定為手機上的預設地圖應用程式比您想像的要容易。請依照以下步驟操作–先決條件步驟–您必須在手機上安裝Gmail。步驟1–開啟AppStore。步驟2–搜尋“Gmail”。步驟3–點選Gmail應用程式旁

升級微信最新版本的步驟(輕鬆掌握微信最新版本的升級方法) 升級微信最新版本的步驟(輕鬆掌握微信最新版本的升級方法) Jun 01, 2024 pm 10:24 PM

不斷推出新版本以提供更好的使用體驗,微信作為中國的社交媒體平台之一。升級微信至最新版本是非常重要的,家人和同事的聯繫、為了保持與朋友、及時了解最新動態。 1.了解最新版本的特性與改進了解最新版本的特性與改進非常重要,在升級微信之前。效能改進和錯誤修復,透過查看微信官方網站或應用程式商店中的更新說明、你可以了解新版本所帶來的各種新功能。 2.檢查目前微信版本我們需要檢查目前手機上已安裝的微信版本、在升級微信之前。點擊,打開微信應用“我”然後選擇,菜單“關於”在這裡你可以看到當前微信的版本號,。 3.打開應

此 Apple ID 尚未在 iTunes Store 中使用:修復 此 Apple ID 尚未在 iTunes Store 中使用:修復 Jun 10, 2024 pm 05:42 PM

使用AppleID登入iTunesStore時,可能會在螢幕上拋出此錯誤提示「此AppleID尚未在iTunesStore中使用」。沒有什麼可擔心的錯誤提示,您可以按照這些解決方案集進行修復。修正1–更改送貨地址此提示出現在iTunesStore中的主要原因是您的AppleID個人資料中沒有正確的地址。步驟1–首先,開啟iPhone上的iPhone設定。步驟2–AppleID應位於所有其他設定的頂部。所以,打開它。步驟3–在那裡,打開“付款和運輸”選項。步驟4–使用面容ID驗證您的存取權限。步驟

Shazam應用程式在iPhone中無法運作:修復 Shazam應用程式在iPhone中無法運作:修復 Jun 08, 2024 pm 12:36 PM

iPhone上的Shazam應用程式有問題? Shazam可協助您透過聆聽歌曲找到歌曲。但是,如果Shazam無法正常工作或無法識別歌曲,則必須手動對其進行故障排除。修復Shazam應用程式不會花費很長時間。因此,無需再浪費時間,請按照以下步驟解決Shazam應用程式的問題。修正1–禁用粗體文字功能iPhone上的粗體文字可能是Shazam無法正常運作的原因。步驟1–您只能從iPhone設定執行此操作。所以,打開它。步驟2–接下來,開啟其中的「顯示和亮度」設定。步驟3–如果您發現啟用了“粗體文本

iPhone螢幕截圖不起作用:如何修復 iPhone螢幕截圖不起作用:如何修復 May 03, 2024 pm 09:16 PM

螢幕截圖功能在您的iPhone上不起作用嗎?截圖非常簡單,因為您只需同時按住「提高音量」按鈕和「電源」按鈕即可抓取手機螢幕。但是,還有其他方法可以在設備上捕獲幀。修復1–使用輔助觸控使用輔助觸控功能截取螢幕截圖。步驟1–轉到您的手機設定。步驟2–接下來,點選以開啟「輔助功能」設定。步驟3–開啟「觸摸」設定。步驟4–接下來,開啟「輔助觸控」設定。步驟5–打開手機上的「輔助觸控」。步驟6–打開“自訂頂級選單”以存取它。步驟7–現在,您只需將這些功能中的任何一個連結到螢幕擷取即可。因此,點擊那裡的首

iPhone中缺少時鐘應用程式:如何修復 iPhone中缺少時鐘應用程式:如何修復 May 03, 2024 pm 09:19 PM

您的手機中缺少時鐘應用程式嗎?日期和時間仍將顯示在iPhone的狀態列上。但是,如果沒有時鐘應用程序,您將無法使用世界時鐘、碼錶、鬧鐘等多項功能。因此,修復時鐘應用程式的缺失應該是您的待辦事項清單的首位。這些解決方案可以幫助您解決此問題。修復1–放置時鐘應用程式如果您錯誤地從主畫面中刪除了時鐘應用程序,您可以將時鐘應用程式放回原位。步驟1–解鎖iPhone並開始向左側滑動,直到到達「應用程式庫」頁面。步驟2–接下來,在搜尋框中搜尋「時鐘」。步驟3–當您在搜尋結果中看到下方的「時鐘」時,請按住它並

Win11系統管理員權限取得步驟詳解 Win11系統管理員權限取得步驟詳解 Mar 08, 2024 pm 09:09 PM

Windows11作為微軟最新推出的作業系統,深受廣大用戶喜愛。在使用Windows11的過程中,有時候我們需要取得系統管理員權限,以便進行一些需要權限的操作。接下來將詳細介紹在Windows11中取得系統管理員權限的步驟。第一步,點擊“開始功能表”,在左下角可以看到Windows圖標,點擊該圖標即可開啟“開始功能表”。第二步,在「開始功能表」中尋找並點擊「

WiFi通話在iPhone上不起作用:修復 WiFi通話在iPhone上不起作用:修復 Jun 03, 2024 am 11:16 AM

無法在iPhone上啟用Wi-Fi通話?通話品質得到改善,您甚至可以從蜂窩網路不那麼強大的遠端位置進行通訊。 Wi-Fi通話也提高了標準通話和視訊通話品質。因此,如果您無法使用手機上的Wi-Fi通話,這些解決方案可能會幫助您解決問題。修復1–手動啟用Wi-Fi通話您必須在iPhone設定中啟用Wi-Fi通話功能。步驟1–為此,您必須打開“設定”。步驟2–接下來,只需向下找到並開啟「電話」設定即可步驟3–在電話設定中,向下捲動並開啟「Wi-Fi通話」設定。步驟4–在Wi-Fi通話頁面中,將「此iPh

See all articles