Skip to content

Commit

Permalink
fix some bug
Browse files Browse the repository at this point in the history
  • Loading branch information
hunterhug committed May 28, 2020
1 parent a21ee64 commit 6554e9f
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 34 deletions.
14 changes: 7 additions & 7 deletions algorithm/search/avl_tree.md
Original file line number Diff line number Diff line change
Expand Up @@ -598,14 +598,14 @@ func (node *AVLTreeNode) Delete(value int64) *AVLTreeNode {
var newNode *AVLTreeNode
// 相当删除了右子树的节点,左边比右边高了,不平衡
if node.BalanceFactor() == 2 {
if node.Left.BalanceFactor() == 1 {
if node.Left.BalanceFactor() >= 0 {
newNode = RightRotation(node)
} else {
newNode = LeftRightRotation(node)
}
// 相当删除了左子树的节点,右边比左边高了,不平衡
} else if node.BalanceFactor() == -2 {
if node.Right.BalanceFactor() == -1 {
if node.Right.BalanceFactor() <= 0 {
newNode = LeftRotation(node)
} else {
newNode = RightLeftRotation(node)
Expand Down Expand Up @@ -712,7 +712,7 @@ func (node *AVLTreeNode) Delete(value int64) *AVLTreeNode {
```
// 相当删除了右子树的节点,左边比右边高了,不平衡
if node.BalanceFactor() == 2 {
if node.Left.BalanceFactor() == 1 {
if node.Left.BalanceFactor() >= 0 {
newNode = RightRotation(node)
} else {
newNode = LeftRightRotation(node)
Expand Down Expand Up @@ -749,7 +749,7 @@ func (node *AVLTreeNode) Delete(value int64) *AVLTreeNode {
1. 根节点 `20` 的左子树比右子树高了 `2` 层,对应:`node.BalanceFactor() == 2`
2. 左子树节点 `13` 并没有失衡,对应:`node.BalanceFactor() == 0`

这个时候,无论使用右旋,还是先左旋后右旋都可以使树恢复平衡,我们的 `else` 判断条件使用了先左旋后右旋
这个时候,无论使用右旋,还是先左旋后右旋都可以使树恢复平衡,我们的 `if` 判断条件使用了右旋

如果是先左旋后右旋,那么旋转后恢复平衡,如图对根结点进行旋转:

Expand All @@ -766,7 +766,7 @@ func (node *AVLTreeNode) Delete(value int64) *AVLTreeNode {
```
// 相当删除了左子树的节点,右边比左边高了,不平衡
if node.BalanceFactor() == -2 {
if node.Right.BalanceFactor() == -1 {
if node.Right.BalanceFactor() <= 0 {
newNode = LeftRotation(node)
} else {
newNode = RightLeftRotation(node)
Expand Down Expand Up @@ -1269,14 +1269,14 @@ func (node *AVLTreeNode) Delete(value int64) *AVLTreeNode {
var newNode *AVLTreeNode
// 相当删除了右子树的节点,左边比右边高了,不平衡
if node.BalanceFactor() == 2 {
if node.Left.BalanceFactor() == 1 {
if node.Left.BalanceFactor() >= 0 {
newNode = RightRotation(node)
} else {
newNode = LeftRightRotation(node)
}
// 相当删除了左子树的节点,右边比左边高了,不平衡
} else if node.BalanceFactor() == -2 {
if node.Right.BalanceFactor() == -1 {
if node.Right.BalanceFactor() <= 0 {
newNode = LeftRotation(node)
} else {
newNode = RightLeftRotation(node)
Expand Down
68 changes: 48 additions & 20 deletions algorithm/search/rb_tree.md
Original file line number Diff line number Diff line change
Expand Up @@ -634,17 +634,17 @@ func (tree *RBTree) fixAfterInsertion(node *RBTNode) {

![](../../picture/br_tree_delete_1.jpg)

图例中 `21``22` 相当于向兄弟借值,而 `1``24` 相当于向父亲的一个值合并后调整。
图例中 `21``22` 相当于向兄弟借值,而 `1``23` 相当于向父亲的一个值合并后调整。

我们仔细分析一下:

图例 `1`,当删除的叶子节点在父亲左边,而兄弟是红色节点,我们可以知道父亲和兄弟的儿子绝对都是黑节点,将兄弟变黑,父亲变红,然后对父亲右链接左旋。如图:
图例 `1`,当删除的叶子节点在父亲左边,而兄弟是红色节点,我们可以知道 `父亲``兄弟的儿子们` 绝对都是黑节点,将兄弟变黑,父亲变红,然后对父亲右链接左旋。如图:

![](../../picture/br_tree_delete_3.jpg)

这时调整后变为了图例 `24`,这种情况实际上是在 `2-3-4` 树中和父亲的值合并,只不过将父亲的值转了一个方向,变为图例 `24` 好分析
这时调整后变为了图例 `23`,这种情况实际上是在 `2-3-4` 树中和父亲的值合并,只不过将父亲的值转了一个方向,可能变为图例 `21,22,23`

图例 `24`,当删除的叶子节点在父亲左边,兄弟节点是黑色,兄弟的儿子们也都是黑色,相当于 `2-3-4` 树和兄弟借不到值了,需要将兄弟变为红色,然后将父亲作为一个整体来删除,向上递归处理(相当于拉了父亲的一个值和兄弟合并)。如图:
图例 `23`,当删除的叶子节点在父亲左边,兄弟节点是黑色,兄弟的儿子们也都是黑色,相当于 `2-3-4` 树和兄弟借不到值了,需要将兄弟变为红色,然后将父亲作为一个整体来删除,向上递归处理(相当于拉了父亲的一个值和兄弟合并)。如图:

![](../../picture/br_tree_delete_4.jpg)

Expand Down Expand Up @@ -725,9 +725,16 @@ func (tree *RBTree) delete(node *RBTNode) {
node.Right = nil
node.Left = nil

// case 1: not enter this logic
// R(del)
// B B
//
// case 2: node's color must be black, and it's son must be red
// B(del) B(del)
// R O O R
//
// 单子树时删除的节点绝对是黑色的,而其唯一子节点必然是红色的
// 现在唯一子节点替换了被删除节点,该节点要变为黑色
// node's color must be black, and it's son must be red
// now son replace it's father, just change color to black
replacement.Color = BLACK
return
Expand Down Expand Up @@ -766,12 +773,12 @@ func (tree *RBTree) fixAfterDeletion(node *RBTNode) {
// 找出兄弟
brother := RightOf(ParentOf(node))

// 兄弟是红色的,对应图例1,那么兄弟变黑,父亲变红,然后对父亲左旋,进入图例23
// 兄弟是红色的,对应图例1,那么兄弟变黑,父亲变红,然后对父亲左旋,进入图例21,22,23
if IsRed(brother) {
SetColor(brother, BLACK)
SetColor(ParentOf(node), RED)
tree.RotateLeft(ParentOf(node))
brother = RightOf(ParentOf(node)) // 图例1调整后进入图例23,兄弟此时变了
brother = RightOf(ParentOf(node)) // 图例1调整后进入图例21,22,23,兄弟此时变了
}

// 兄弟是黑色的,对应图例21,22,23
Expand Down Expand Up @@ -801,12 +808,12 @@ func (tree *RBTree) fixAfterDeletion(node *RBTNode) {
// 找出兄弟
brother := RightOf(ParentOf(node))

// 兄弟是红色的,对应图例3,那么兄弟变黑,父亲变红,然后对父亲右旋,进入图例43
// 兄弟是红色的,对应图例3,那么兄弟变黑,父亲变红,然后对父亲右旋,进入图例41,42,43
if IsRed(brother) {
SetColor(brother, BLACK)
SetColor(ParentOf(node), RED)
tree.RotateRight(ParentOf(node))
brother = LeftOf(ParentOf(node)) // 图例3调整后进入图例43,兄弟此时变了
brother = LeftOf(ParentOf(node)) // 图例3调整后进入图例41,42,43,兄弟此时变了
}

// 兄弟是黑色的,对应图例41,42,43
Expand Down Expand Up @@ -904,9 +911,16 @@ func (tree *RBTree) delete(node *RBTNode) {
node.Right = nil
node.Left = nil

// case 1: not enter this logic
// R(del)
// B B
//
// case 2: node's color must be black, and it's son must be red
// B(del) B(del)
// R O O R
//
// 单子树时删除的节点绝对是黑色的,而其唯一子节点必然是红色的
// 现在唯一子节点替换了被删除节点,该节点要变为黑色
// node's color must be black, and it's son must be red
// now son replace it's father, just change color to black
replacement.Color = BLACK
return
Expand Down Expand Up @@ -992,9 +1006,16 @@ func (tree *RBTree) delete(node *RBTNode) {
node.Right = nil
node.Left = nil

// case 1: not enter this logic
// R(del)
// B B
//
// case 2: node's color must be black, and it's son must be red
// B(del) B(del)
// R O O R
//
// 单子树时删除的节点绝对是黑色的,而其唯一子节点必然是红色的
// 现在唯一子节点替换了被删除节点,该节点要变为黑色
// node's color must be black, and it's son must be red
// now son replace it's father, just change color to black
replacement.Color = BLACK
return
Expand Down Expand Up @@ -1046,12 +1067,12 @@ func (tree *RBTree) fixAfterDeletion(node *RBTNode) {
// 找出兄弟
brother := RightOf(ParentOf(node))

// 兄弟是红色的,对应图例1,那么兄弟变黑,父亲变红,然后对父亲左旋,进入图例23
// 兄弟是红色的,对应图例1,那么兄弟变黑,父亲变红,然后对父亲左旋,进入图例21,22,23
if IsRed(brother) {
SetColor(brother, BLACK)
SetColor(ParentOf(node), RED)
tree.RotateLeft(ParentOf(node))
brother = RightOf(ParentOf(node)) // 图例1调整后进入图例23,兄弟此时变了
brother = RightOf(ParentOf(node)) // 图例1调整后进入图例21,22,23,兄弟此时变了
}

// 兄弟是黑色的,对应图例21,22,23
Expand Down Expand Up @@ -1081,12 +1102,12 @@ func (tree *RBTree) fixAfterDeletion(node *RBTNode) {
// 找出兄弟
brother := RightOf(ParentOf(node))

// 兄弟是红色的,对应图例3,那么兄弟变黑,父亲变红,然后对父亲右旋,进入图例43
// 兄弟是红色的,对应图例3,那么兄弟变黑,父亲变红,然后对父亲右旋,进入图例41,42,43
if IsRed(brother) {
SetColor(brother, BLACK)
SetColor(ParentOf(node), RED)
tree.RotateRight(ParentOf(node))
brother = LeftOf(ParentOf(node)) // 图例3调整后进入图例43,兄弟此时变了
brother = LeftOf(ParentOf(node)) // 图例3调整后进入图例41,42,43,兄弟此时变了
}

// 兄弟是黑色的,对应图例41,42,43
Expand Down Expand Up @@ -1578,9 +1599,16 @@ func (tree *RBTree) delete(node *RBTNode) {
node.Right = nil
node.Left = nil

// case 1: not enter this logic
// R(del)
// B B
//
// case 2: node's color must be black, and it's son must be red
// B(del) B(del)
// R O O R
//
// 单子树时删除的节点绝对是黑色的,而其唯一子节点必然是红色的
// 现在唯一子节点替换了被删除节点,该节点要变为黑色
// node's color must be black, and it's son must be red
// now son replace it's father, just change color to black
replacement.Color = BLACK
return
Expand Down Expand Up @@ -1619,12 +1647,12 @@ func (tree *RBTree) fixAfterDeletion(node *RBTNode) {
// 找出兄弟
brother := RightOf(ParentOf(node))

// 兄弟是红色的,对应图例1,那么兄弟变黑,父亲变红,然后对父亲左旋,进入图例23
// 兄弟是红色的,对应图例1,那么兄弟变黑,父亲变红,然后对父亲左旋,进入图例21,22,23
if IsRed(brother) {
SetColor(brother, BLACK)
SetColor(ParentOf(node), RED)
tree.RotateLeft(ParentOf(node))
brother = RightOf(ParentOf(node)) // 图例1调整后进入图例23,兄弟此时变了
brother = RightOf(ParentOf(node)) // 图例1调整后进入图例21,22,23,兄弟此时变了
}

// 兄弟是黑色的,对应图例21,22,23
Expand Down Expand Up @@ -1654,12 +1682,12 @@ func (tree *RBTree) fixAfterDeletion(node *RBTNode) {
// 找出兄弟
brother := RightOf(ParentOf(node))

// 兄弟是红色的,对应图例3,那么兄弟变黑,父亲变红,然后对父亲右旋,进入图例43
// 兄弟是红色的,对应图例3,那么兄弟变黑,父亲变红,然后对父亲右旋,进入图例41,42,43
if IsRed(brother) {
SetColor(brother, BLACK)
SetColor(ParentOf(node), RED)
tree.RotateRight(ParentOf(node))
brother = LeftOf(ParentOf(node)) // 图例3调整后进入图例43,兄弟此时变了
brother = LeftOf(ParentOf(node)) // 图例3调整后进入图例41,42,43,兄弟此时变了
}

// 兄弟是黑色的,对应图例41,42,43
Expand Down
4 changes: 2 additions & 2 deletions code/avltree/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,14 +325,14 @@ func (node *AVLTreeNode) Delete(value int64) *AVLTreeNode {
var newNode *AVLTreeNode
// 相当删除了右子树的节点,左边比右边高了,不平衡
if node.BalanceFactor() == 2 {
if node.Left.BalanceFactor() == 1 {
if node.Left.BalanceFactor() >= 0 {
newNode = RightRotation(node)
} else {
newNode = LeftRightRotation(node)
}
// 相当删除了左子树的节点,右边比左边高了,不平衡
} else if node.BalanceFactor() == -2 {
if node.Right.BalanceFactor() == -1 {
if node.Right.BalanceFactor() <= 0 {
newNode = LeftRotation(node)
} else {
newNode = RightLeftRotation(node)
Expand Down
17 changes: 12 additions & 5 deletions code/rbt/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,9 +302,16 @@ func (tree *RBTree) delete(node *RBTNode) {
node.Right = nil
node.Left = nil

// case 1: not enter this logic
// R(del)
// B B
//
// case 2: node's color must be black, and it's son must be red
// B(del) B(del)
// R O O R
//
// 单子树时删除的节点绝对是黑色的,而其唯一子节点必然是红色的
// 现在唯一子节点替换了被删除节点,该节点要变为黑色
// node's color must be black, and it's son must be red
// now son replace it's father, just change color to black
replacement.Color = BLACK
return
Expand Down Expand Up @@ -343,12 +350,12 @@ func (tree *RBTree) fixAfterDeletion(node *RBTNode) {
// 找出兄弟
brother := RightOf(ParentOf(node))

// 兄弟是红色的,对应图例1,那么兄弟变黑,父亲变红,然后对父亲左旋,进入图例23
// 兄弟是红色的,对应图例1,那么兄弟变黑,父亲变红,然后对父亲左旋,进入图例21,22,23
if IsRed(brother) {
SetColor(brother, BLACK)
SetColor(ParentOf(node), RED)
tree.RotateLeft(ParentOf(node))
brother = RightOf(ParentOf(node)) // 图例1调整后进入图例23,兄弟此时变了
brother = RightOf(ParentOf(node)) // 图例1调整后进入图例21,22,23,兄弟此时变了
}

// 兄弟是黑色的,对应图例21,22,23
Expand Down Expand Up @@ -378,12 +385,12 @@ func (tree *RBTree) fixAfterDeletion(node *RBTNode) {
// 找出兄弟
brother := RightOf(ParentOf(node))

// 兄弟是红色的,对应图例3,那么兄弟变黑,父亲变红,然后对父亲右旋,进入图例43
// 兄弟是红色的,对应图例3,那么兄弟变黑,父亲变红,然后对父亲右旋,进入图例41,42,43
if IsRed(brother) {
SetColor(brother, BLACK)
SetColor(ParentOf(node), RED)
tree.RotateRight(ParentOf(node))
brother = LeftOf(ParentOf(node)) // 图例3调整后进入图例43,兄弟此时变了
brother = LeftOf(ParentOf(node)) // 图例3调整后进入图例41,42,43,兄弟此时变了
}

// 兄弟是黑色的,对应图例41,42,43
Expand Down

0 comments on commit 6554e9f

Please sign in to comment.