Golang实现的红黑树

前端之家收集整理的这篇文章主要介绍了Golang实现的红黑树前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

红黑树是一种基于二叉查找树的数据结构,它具有如下性质:

(1) 二叉查找树的性质它都有

(2) 每个节点都有一个颜色属性,每个节点或是红的或是黑的

(3) 根节点必须是黑的

(4) 每个叶子节点(nil节点)为黑

(5) 如果一个节点为红的,那么它的两个孩子都是黑的

(6) 每个节点到它子孙叶子节点的路径上的黑色节点个数是相同的


相比二叉查找树,红黑树在添加删除元素的同时还需要调整树的深度,所以需要用到对树结构的一些旋转操作,下面的实例代码给的非常详尽了,可以看看LeftRotate()和RightRotate()函数式如何实现旋转的。如果有人发现了BUG请在留言中发表~



这个代码是在之前的"Golang以OO的方式实现二叉查找树"里的代码加工实现的,因为本人技术不到位。。。出了好几次BUG,修修补补,写了这么一大堆代码,大家凑合着看。。。:

  1. package main
  2.  
  3. import (
  4. "fmt"
  5. )
  6.  
  7. var count int
  8.  
  9. type TreeNode struct {
  10. data float64
  11. color string //比二叉查找树要多出一个颜色属性
  12. lchild *TreeNode
  13. rchild *TreeNode
  14. parent *TreeNode
  15. }
  16.  
  17. type RBTree struct {
  18. root *TreeNode
  19. cur *TreeNode
  20. create *TreeNode
  21. }
  22.  
  23. func (rbt *RBTree) Add(data float64) {
  24. rbt.create = new(TreeNode)
  25. rbt.create.data = data
  26. rbt.create.color = "red"
  27.  
  28. if !rbt.IsEmpty() {
  29. rbt.cur = rbt.root
  30. for {
  31. if data < rbt.cur.data {
  32. //如果要插入的值比当前节点的值小,则当前节点指向当前节点的左孩子,如果
  33. //左孩子为空,就在这个左孩子上插入新值
  34. if rbt.cur.lchild == nil {
  35. rbt.cur.lchild = rbt.create
  36. rbt.create.parent = rbt.cur
  37. break
  38. } else {
  39. rbt.cur = rbt.cur.lchild
  40. }
  41.  
  42. } else if data > rbt.cur.data {
  43. //如果要插入的值比当前节点的值大,则当前节点指向当前节点的右孩子,如果
  44. //右孩子为空,就在这个右孩子上插入新值
  45. if rbt.cur.rchild == nil {
  46. rbt.cur.rchild = rbt.create
  47. rbt.create.parent = rbt.cur
  48. break
  49. } else {
  50. rbt.cur = rbt.cur.rchild
  51. }
  52.  
  53. } else {
  54. //如果要插入的值在树中已经存在,则退出
  55. return
  56. }
  57. }
  58.  
  59. } else {
  60. rbt.root = rbt.create
  61. rbt.root.color = "black"
  62. rbt.root.parent = nil
  63. return
  64. }
  65.  
  66. //插入节点后对红黑性质进行修复
  67. rbt.insertBalanceFixup(rbt.create)
  68. }
  69.  
  70. func (rbt *RBTree) Delete(data float64) {
  71. var (
  72. deleteNode func(node *TreeNode)
  73. node *TreeNode = rbt.Search(data)
  74. parent *TreeNode
  75. revise string
  76. )
  77.  
  78. if node == nil {
  79. return
  80. } else {
  81. parent = node.parent
  82. }
  83.  
  84. //下面这小块代码用来判断替代被删节点位置的节点是哪个后代
  85. if node.lchild == nil && node.rchild == nil {
  86. revise = "none"
  87. } else if parent == nil {
  88. revise = "root"
  89. } else if node == parent.lchild {
  90. revise = "left"
  91. } else if node == parent.rchild {
  92. revise = "right"
  93. }
  94.  
  95. deleteNode = func(node *TreeNode) {
  96. if node == nil {
  97. return
  98. }
  99.  
  100. if node.lchild == nil && node.rchild == nil {
  101. //如果要删除的节点没有孩子,直接删掉它就可以(毫无挂念~.~!)
  102. if node == rbt.root {
  103. rbt.root = nil
  104. } else {
  105. if node.parent.lchild == node {
  106. node.parent.lchild = nil
  107. } else {
  108. node.parent.rchild = nil
  109. }
  110. }
  111.  
  112. } else if node.lchild != nil && node.rchild == nil {
  113. //如果要删除的节点只有左孩子或右孩子,让这个节点的父节点指向它的指针指向它的
  114. //孩子即可
  115. if node == rbt.root {
  116. node.lchild.parent = nil
  117. rbt.root = node.lchild
  118. } else {
  119. node.lchild.parent = node.parent
  120. if node.parent.lchild == node {
  121. node.parent.lchild = node.lchild
  122. } else {
  123. node.parent.rchild = node.lchild
  124. }
  125. }
  126.  
  127. } else if node.lchild == nil && node.rchild != nil {
  128. if node == rbt.root {
  129. node.rchild.parent = nil
  130. rbt.root = node.rchild
  131. } else {
  132. node.rchild.parent = node.parent
  133. if node.parent.lchild == node {
  134. node.parent.lchild = node.rchild
  135. } else {
  136. node.parent.rchild = node.rchild
  137. }
  138. }
  139.  
  140. } else {
  141. //如果要删除的节点既有左孩子又有右孩子,就把这个节点的直接后继的值赋给这个节
  142. //点,然后删除直接后继节点即可
  143. successor := rbt.GetSuccessor(node.data)
  144. node.data = successor.data
  145. node.color = successor.color
  146. deleteNode(successor)
  147. }
  148. }
  149.  
  150. deleteNode(node)
  151. if node.color == "black" {
  152. if revise == "root" {
  153. rbt.deleteBalanceFixup(rbt.root)
  154. } else if revise == "left" {
  155. rbt.deleteBalanceFixup(parent.lchild)
  156. } else if revise == "right" {
  157. rbt.deleteBalanceFixup(parent.rchild)
  158. }
  159. }
  160. //至于为什么删除的为红节点时不用调节平衡,那本黑色的《算法导论(第二版)》是这么解释的:
  161. //当删除红节点时
  162. //(1) 树中个节点的黑高度都没有变化
  163. //(2) 不存在两个相邻的红色节点
  164. //(3) 如果删除的节点是红的,就不可能是根,所以根依然是黑色的
  165. }
  166.  
  167. //这个函数用于在红黑树执行插入操作后,修复红黑性质
  168. func (rbt *RBTree) insertBalanceFixup(insertnode *TreeNode) {
  169. var uncle *TreeNode
  170.  
  171. for insertnode.color == "red" && insertnode.parent.color == "red" {
  172. //获取新插入的节点的叔叔节点(与父节点同根的另一个节点)
  173. if insertnode.parent == insertnode.parent.parent.lchild {
  174. uncle = insertnode.parent.parent.rchild
  175. } else {
  176. uncle = insertnode.parent.parent.lchild
  177. }
  178.  
  179. if uncle != nil && uncle.color == "red" {
  180. //如果叔叔节点是红色,就按照如下图所示变化(●->黑,○->红):
  181. // | |
  182. // 1● 1○ <-new node ptr come here
  183. // / \ --------\ / \
  184. // 2○ ○3 --------/ 2● ●3
  185. // / /
  186. //4○ <-new node ptr 4○
  187. //
  188. //这种情况可以一直循环,知道new node ptr指到root时退出(root颜色依然为黑)
  189. uncle.color,insertnode.parent.color = "black","black"
  190. insertnode = insertnode.parent.parent
  191. if insertnode == rbt.root || insertnode == nil {
  192. return
  193. }
  194. insertnode.color = "red"
  195.  
  196. } else {
  197. //如果叔叔节点为空或叔叔节点为黑色,就按照如下图所示变化:
  198. // | |
  199. // 1● <-right rotate 2●
  200. // / \ --------\ / \
  201. // 2○ ●3 --------/ 4○ ○1
  202. // / \
  203. //4○ <-new node ptr ●3
  204. //
  205. //当然,这只是叔叔节点为黑时的一种情况,如果上图的节点4为2节点的右孩子,则
  206. //可以先在2节点处向左旋转,这样就转换成了上图这种情况了。另外两种情况自己想
  207. //想就明白了
  208. if insertnode.parent == insertnode.parent.parent.lchild {
  209. if insertnode == insertnode.parent.rchild {
  210. insertnode = insertnode.parent
  211. rbt.LeftRotate(insertnode)
  212. }
  213. insertnode = insertnode.parent
  214. insertnode.color = "black"
  215. insertnode = insertnode.parent
  216. insertnode.color = "red"
  217. rbt.RightRotate(insertnode)
  218.  
  219. } else {
  220. if insertnode == insertnode.parent.lchild {
  221. insertnode = insertnode.parent
  222. rbt.RightRotate(insertnode)
  223. }
  224. insertnode = insertnode.parent
  225. insertnode.color = "black"
  226. insertnode = insertnode.parent
  227. insertnode.color = "red"
  228. rbt.LeftRotate(insertnode)
  229. }
  230. return
  231. }
  232. }
  233. }
  234.  
  235. //这个函数用于在红黑树执行删除操作后,修复红黑性质
  236. func (rbt *RBTree) deleteBalanceFixup(node *TreeNode) {
  237. var brother *TreeNode
  238.  
  239. for node != rbt.root && node.color == "black" {
  240. //删除时的红黑修复需要考虑四种情况(下面的“X”指取代了被删节点位置的新节点)
  241. // (1) X的兄弟节点是红色的:
  242. // | |
  243. // 1● 3●
  244. // / \ --------\ / \
  245. // X-> 2● ○3 <-brother --------/ 1○ ●5
  246. // / \ / \
  247. // 4● ●5 X-> 2● ●4
  248. //
  249. // (2) X的兄弟节点是黑色的,而且兄弟节点的两个孩子都是黑色的:
  250. // | |
  251. // 1○ X-> 1○
  252. // / \ --------\ / \
  253. // X-> 2● ●3 <-brother --------/ 2● ○3
  254. // / \ / \
  255. // 4● ●5 4● ●5
  256. //
  257. // (3) X的兄弟节点是黑色的,兄弟的左孩子是红色的,右孩子是黑色的:
  258. // | |
  259. // 1○ 1○
  260. // / \ --------\ / \
  261. // X-> 2● ●3 <-brother --------/ X->2● ●4
  262. // / \ \
  263. // 4○ ●5 ○3
  264. // \
  265. // ●5
  266. //
  267. // (4) X的兄弟节点是黑色的,兄弟的右孩子是红色的:
  268. // | |
  269. // 1○ 3○ X->root and loop while end
  270. // / \ --------\ / \
  271. // X-> 2● ●3 <-brother --------/ 1● ●5
  272. // / \ / \
  273. // 4○ ○5 2● ○4
  274. //
  275. //以上是兄弟节点在X右边时的情况,在X左边是取相反即可!
  276. if node.parent.lchild == node && node.parent.rchild != nil {
  277. brother = node.parent.rchild
  278. if brother.color == "red" {
  279. brother.color = "black"
  280. node.parent.color = "red"
  281. rbt.LeftRotate(node.parent)
  282. } else if brother.color == "black" && brother.lchild != nil && brother.lchild.color == "black" && brother.rchild != nil && brother.rchild.color == "black" {
  283. brother.color = "red"
  284. node = node.parent
  285. } else if brother.color == "black" && brother.lchild != nil && brother.lchild.color == "red" && brother.rchild != nil && brother.rchild.color == "black" {
  286. brother.color = "red"
  287. brother.lchild.color = "black"
  288. rbt.RightRotate(brother)
  289. } else if brother.color == "black" && brother.rchild != nil && brother.rchild.color == "red" {
  290. brother.color = "red"
  291. brother.rchild.color = "black"
  292. brother.parent.color = "black"
  293. rbt.LeftRotate(brother.parent)
  294. node = rbt.root
  295. }
  296.  
  297. } else if node.parent.rchild == node && node.parent.lchild != nil {
  298. brother = node.parent.lchild
  299. if brother.color == "red" {
  300. brother.color = "black"
  301. node.parent.color = "red"
  302. rbt.RightRotate(node.parent)
  303. } else if brother.color == "black" && brother.lchild != nil && brother.lchild.color == "black" && brother.rchild != nil && brother.rchild.color == "black" {
  304. brother.color = "red"
  305. node = node.parent
  306. } else if brother.color == "black" && brother.lchild != nil && brother.lchild.color == "black" && brother.rchild != nil && brother.rchild.color == "red" {
  307. brother.color = "red"
  308. brother.rchild.color = "black"
  309. rbt.LeftRotate(brother)
  310. } else if brother.color == "black" && brother.lchild != nil && brother.lchild.color == "red" {
  311. brother.color = "red"
  312. brother.lchild.color = "black"
  313. brother.parent.color = "black"
  314. rbt.RightRotate(brother.parent)
  315. node = rbt.root
  316. }
  317. } else {
  318. return
  319. }
  320. }
  321. }
  322.  
  323. func (rbt RBTree) GetRoot() *TreeNode {
  324. if rbt.root != nil {
  325. return rbt.root
  326. }
  327. return nil
  328. }
  329.  
  330. func (rbt RBTree) IsEmpty() bool {
  331. if rbt.root == nil {
  332. return true
  333. }
  334. return false
  335. }
  336.  
  337. func (rbt RBTree) InOrderTravel() {
  338. var inOrderTravel func(node *TreeNode)
  339.  
  340. inOrderTravel = func(node *TreeNode) {
  341. if node != nil {
  342. inOrderTravel(node.lchild)
  343. fmt.Printf("%g ",node.data)
  344. inOrderTravel(node.rchild)
  345. }
  346. }
  347.  
  348. inOrderTravel(rbt.root)
  349. }
  350.  
  351. func (rbt RBTree) Search(data float64) *TreeNode {
  352. //和Add操作类似,只要按照比当前节点小就往左孩子上拐,比当前节点大就往右孩子上拐的思路
  353. //一路找下去,知道找到要查找的值返回即可
  354. rbt.cur = rbt.root
  355. for {
  356. if rbt.cur == nil {
  357. return nil
  358. }
  359.  
  360. if data < rbt.cur.data {
  361. rbt.cur = rbt.cur.lchild
  362. } else if data > rbt.cur.data {
  363. rbt.cur = rbt.cur.rchild
  364. } else {
  365. return rbt.cur
  366. }
  367. }
  368. }
  369.  
  370. func (rbt RBTree) GetDeepth() int {
  371. var getDeepth func(node *TreeNode) int
  372.  
  373. getDeepth = func(node *TreeNode) int {
  374. if node == nil {
  375. return 0
  376. }
  377. if node.lchild == nil && node.rchild == nil {
  378. return 1
  379. }
  380. var (
  381. ldeepth int = getDeepth(node.lchild)
  382. rdeepth int = getDeepth(node.rchild)
  383. )
  384. if ldeepth > rdeepth {
  385. return ldeepth + 1
  386. } else {
  387. return rdeepth + 1
  388. }
  389. }
  390.  
  391. return getDeepth(rbt.root)
  392. }
  393.  
  394. func (rbt RBTree) GetMin() float64 {
  395. //根据二叉查找树的性质,树中最左边的节点就是值最小的节点
  396. if rbt.root == nil {
  397. return -1
  398. }
  399. rbt.cur = rbt.root
  400. for {
  401. if rbt.cur.lchild != nil {
  402. rbt.cur = rbt.cur.lchild
  403. } else {
  404. return rbt.cur.data
  405. }
  406. }
  407. }
  408.  
  409. func (rbt RBTree) GetMax() float64 {
  410. //根据二叉查找树的性质,树中最右边的节点就是值最大的节点
  411. if rbt.root == nil {
  412. return -1
  413. }
  414. rbt.cur = rbt.root
  415. for {
  416. if rbt.cur.rchild != nil {
  417. rbt.cur = rbt.cur.rchild
  418. } else {
  419. return rbt.cur.data
  420. }
  421. }
  422. }
  423.  
  424. func (rbt RBTree) GetPredecessor(data float64) *TreeNode {
  425. getMax := func(node *TreeNode) *TreeNode {
  426. if node == nil {
  427. return nil
  428. }
  429. for {
  430. if node.rchild != nil {
  431. node = node.rchild
  432. } else {
  433. return node
  434. }
  435. }
  436. }
  437.  
  438. node := rbt.Search(data)
  439. if node != nil {
  440. if node.lchild != nil {
  441. //如果这个节点有左孩子,那么它的直接前驱就是它左子树的最右边的节点,因为比这
  442. //个节点值小的节点都在左子树,而这些节点中值最大的就是这个最右边的节点
  443. return getMax(node.lchild)
  444. } else {
  445. //如果这个节点没有左孩子,那么就沿着它的父节点找,知道某个父节点的父节点的右
  446. //孩子就是这个父节点,那么这个父节点的父节点就是直接前驱
  447. for {
  448. if node == nil || node.parent == nil {
  449. break
  450. }
  451. if node == node.parent.rchild {
  452. return node.parent
  453. }
  454. node = node.parent
  455. }
  456. }
  457. }
  458.  
  459. return nil
  460. }
  461.  
  462. func (rbt RBTree) GetSuccessor(data float64) *TreeNode {
  463. getMin := func(node *TreeNode) *TreeNode {
  464. if node == nil {
  465. return nil
  466. }
  467. for {
  468. if node.lchild != nil {
  469. node = node.lchild
  470. } else {
  471. return node
  472. }
  473. }
  474. }
  475.  
  476. //参照寻找直接前驱的函数对比着看
  477. node := rbt.Search(data)
  478. if node != nil {
  479. if node.rchild != nil {
  480. return getMin(node.rchild)
  481. } else {
  482. for {
  483. if node == nil || node.parent == nil {
  484. break
  485. }
  486. if node == node.parent.lchild {
  487. return node.parent
  488. }
  489. node = node.parent
  490. }
  491. }
  492. }
  493.  
  494. return nil
  495. }
  496.  
  497. func (rbt *RBTree) Clear() {
  498. rbt.root = nil
  499. rbt.cur = nil
  500. rbt.create = nil
  501. }
  502.  
  503. /**
  504. * 旋转图解(以向左旋转为例):
  505. * | |
  506. * ○ <-left rotate ●
  507. * \ ----------\ / \
  508. * ● ----------/ ○ ●r
  509. * / \ \
  510. * l● ●r l●
  511. *
  512. *
  513. *
  514. * | |
  515. * ○ <-left rotate ●
  516. * \ ----------\ / \
  517. * ● ----------/ ○ ●
  518. * \ \
  519. * ● nil <-don't forget it should be nil
  520. */
  521. func (rbt *RBTree) LeftRotate(node *TreeNode) {
  522. if node.rchild == nil {
  523. return
  524. }
  525.  
  526. right_child := node.rchild
  527. //将要旋转的节点的右孩子的左孩子赋给这个节点的右孩子,这里最好按如下3行代码的顺序写,
  528. //否则该节点的右孩子的左孩子为nil时,很容易忘记把这个节点的右孩子也置为nil.
  529. node.rchild = right_child.lchild
  530. if node.rchild != nil {
  531. node.rchild.parent = node
  532. }
  533.  
  534. //让要旋转的节点的右孩子的父节点指针指向当前节点父节点。如果父节点是根节点要特别处理
  535. right_child.parent = node.parent
  536. if node.parent == nil {
  537. rbt.root = right_child
  538. } else {
  539. if node.parent.lchild == node {
  540. node.parent.lchild = right_child
  541. } else {
  542. node.parent.rchild = right_child
  543. }
  544. }
  545.  
  546. //上面的准备工作完毕了,就可以开始旋转了,让要旋转的节点的右孩子的左孩子指向该节点,
  547. //别忘了把这个被旋转的节点的父节点指针指向新的父节点
  548. right_child.lchild = node
  549. node.parent = right_child
  550. }
  551.  
  552. func (rbt *RBTree) RightRotate(node *TreeNode) {
  553. //向右旋转的过程与LeftRotate()正好相反
  554. if node.lchild == nil {
  555. return
  556. }
  557.  
  558. left_child := node.lchild
  559. node.lchild = left_child.rchild
  560. if node.lchild != nil {
  561. node.lchild.parent = node
  562. }
  563.  
  564. left_child.parent = node.parent
  565. if node.parent == nil {
  566. rbt.root = left_child
  567. } else {
  568. if node.parent.lchild == node {
  569. node.parent.lchild = left_child
  570. } else {
  571. node.parent.rchild = left_child
  572. }
  573. }
  574. left_child.rchild = node
  575. node.parent = left_child
  576. }
  577.  
  578. func main() {
  579. var rbt RBTree
  580. rbt.Add(9)
  581. rbt.Add(8)
  582. rbt.Add(7)
  583. rbt.Add(6)
  584. rbt.Add(5)
  585. rbt.Add(4)
  586. rbt.Add(3)
  587. rbt.Add(2)
  588. rbt.Add(1)
  589. fmt.Println(rbt.GetDeepth())
  590. }



运行结果如下:


如果是二叉查找树,那么树的深度就会为9,这样就和普通的线性结构没什么区别了,可见红黑树的确是一棵更好的二叉查找树。



如果转载请注明出处:http://blog.csdn.net/gophers/article/details/23608025

猜你在找的Go相关文章