# BST

Binary Search Tree, is a node-based binary tree data structure which has the following properties:

1. The left subtree of a node contains only nodes with keys less than the node’s key.
2. The right subtree of a node contains only nodes with keys greater than the node’s key.
3. The left and right subtree each must also be a binary search tree.
There must be no duplicate nodes.

## Searching a key

To search a given key in Bianry Search Tree, we first compare it with root, if the key is present at root, we return root. If key is greater than root’s key, we recur for right subtree of root node. Otherwise we recur for left subtree.

// C function to search a given key in a given BST
struct node* search(struct node* root, int key)
{
// Base Cases: root is null or key is present at root
if (root == NULL || root->key == key)
return root;

/**
* 如果root节点的key不等于指定的key，那么必然在其子树中查找
* 如同以下代码，当root->key < key时，返回的节点由search(root->right, key)告诉我
*/
// Key is greater than root's key
if (root->key < key)
return search(root->right, key); //　递归深入到右子树

// Key is smaller than root's key
return search(root->left, key);
}

## Insertion of a key

A new key is always inserted at leaf. We start searching a key from root till we hit a leaf node. Once a leaf node is found, the new node is added as a child of the leaf node.

         100                               100
/   \        Insert 40            /    \
20     500    --------->          20     500
/  \                              /  \
10   30                           10   30
\
40
/* A utility function to insert a new node with given key in BST */
struct node* insert(struct node* node, int key)
{
/* If the tree is empty, return a new node */
// base case
if (node == NULL) return newNode(key);

/* Otherwise, recur down the tree */
if (key < node->key)
node->left  = insert(node->left, key);
else if (key > node->key)
node->right = insert(node->right, key);

/* return the (unchanged) node pointer */
return node;
}

Time Complexity: The worst case time complexity of search and insert operations is O(h) where h is height of Binary Search Tree. In worst case, we may have to travel from root to the deepest leaf node. The height of a skewed tree may become n and the time complexity of search and insert operation may become O(n).

## Deletion of a node

1) Node to be deleted is leaf: Simply remove from the tree.

              50                            50
/     \         delete(20)      /   \
30      70       --------->    30     70
/  \    /  \                     \    /  \
20   40  60   80                   40  60   80

2) Node to be deleted has only one child: Copy the child to the node and delete the child

              50                            50
/     \         delete(30)      /   \
30      70       --------->    40     70
\    /  \                          /  \
40  60   80                       60   80

3) Node to be deleted has two children: Find inorder successor of the node. Copy contents of the inorder successor to the node and delete the inorder successor. Note that inorder predecessor can also be used.

              50                            60
/     \         delete(50)      /   \
40      70       --------->    40    70
/  \                            \
60   80                           80

The important thing to note is, inorder successor is needed only when right child is not empty. In this particular case, inorder successor can be obtained by finding the minimum value in right child of the node.

/* Given a non-empty binary search tree, return the node with minimum
key value found in that tree. Note that the entire tree does not
need to be searched. */
struct node * minValueNode(struct node* node)
{
struct node* current = node;

/* loop down to find the leftmost leaf */
while (current->left != NULL)
current = current->left;

return current;
}

/* Given a binary search tree and a key, this function deletes the key
and returns the new root */
struct node* deleteNode(struct node* root, int key)
{
// base case 1 : Tree is NULL
if (root == NULL) return root;

// If the key to be deleted is smaller than the root's key,
// then it lies in left subtree
if (key < root->key)
root->left = deleteNode(root->left, key);

// If the key to be deleted is greater than the root's key,
// then it lies in right subtree
else if (key > root->key)
root->right = deleteNode(root->right, key);

// if key is same as root's key, then This is the node
// to be deleted
else
{
// base case 2
// node with only one child or no child
if (root->left == NULL)
{
struct node *temp = root->right;
free(root);
return temp;
}
else if (root->right == NULL)
{
struct node *temp = root->left;
free(root);
return temp;
}

// node with two children: Get the inorder successor (smallest
// in the right subtree)
struct node* temp = minValueNode(root->right);

// Copy the inorder successor's content to this node
root->key = temp->key;

// Delete the inorder successor
// 该被删node，要么没有孩子，要么只有右孩子，因此可以以上面的方式删除。
// 此处必须这样递归删除，是因为我们没有办法拿到temp节点的父亲节点，无法将父亲节点的孩子节点置NULL
root->right = deleteNode(root->right, temp->key);
}

// 1. 当被删除节点无孩子或只有一个孩子的时候，可以直接删除，
//    并将其后继代替其位置即可，因此返回temp
// 2. 当被删除节点有两个孩子的时候，我们只是对key作了替换，没有改变该node的拓卜结构，因此返回的仍然是该节点
// 3. 当前节点并非所要删除的node时，返回的自然仍是该node
// 2和3可以合并成以下的 return root
return root;

/**
*                      10
*                    /    \
*                   9      15
*                 /      /    \
*                6      12     18
*                             /
*                            16
*
* 假设所删节点是15，那么将15替换成16后，会执行删除原来值为16的node的操作
* 删除该node后，递归将往上逐层返回到原来值为15的node，在逐层网上返回。
*
* 总结一点就是：找到那个被删除的点，递归即逐层返回。
*
*/

}    

Time Complexity: The worst case time complexity of delete operation is O(h) where h is height of Binary Search Tree. In worst case, we may have to travel from root to the deepest leaf node. The height of a skewed tree may become n and the time complexity of delete operation may become O(n)

# AVL Tree

AVL tree is a self-balancing Binary Search Tree (BST) where the difference between heights of left and right subtrees cannot be more than one for all nodes.

## 0 Why AVL Trees?

Most of the BST operations (e.g., search, max, min, insert, delete.. etc) take O(h) time where h is the height of the BST. The cost of these operations may become O(n) for a skewed Binary tree. If we make sure that height of the tree remains O(Logn) after every insertion and deletion, then we can guarantee an upper bound of O(Logn) for all these operations. The height of an AVL tree is always O(Logn) where n is the number of nodes in the tree.

## 1 Insertion

To make sure that the given tree remains AVL after every insertion, we must augment the standard BST insert operation to perform some re-balancing. Following are two basic operations that can be performed to re-balance a BST without violating the BST property (keys(left) < key(root) < keys(right)). 1) Left Rotation 2) Right Rotation

T1, T2 and T3 are subtrees of the tree rooted with y (on left side) or x (on right side)
y                               x
/ \     Right Rotation          /  \
x   T3   – – – – – – – >   T1   y
/ \       < - - - - - - -            / \
T1  T2     Left Rotation            T2  T3
Keys in both of the above trees follow the following order
keys(T1) < key(x) < keys(T2) < key(y) < keys(T3)
So BST property is not violated anywhere.

### Steps to follow for insertion

Let the newly inserted node be w
1) Perform standard BST insert for w.
2) Starting from w, travel up and find the first unbalanced node. Let z be the first unbalanced node, y be the child of z that comes on the path from w to z and x be the grandchild of z that comes on the path from w to z.
3) Re-balance the tree by performing appropriate rotations on the subtree rooted with z. There can be 4 possible cases that needs to be handled as x, y and z can be arranged in 4 ways. Following are the possible 4 arrangements:
a) y is left child of z and x is left child of y (Left Left Case)
b) y is left child of z and x is right child of y (Left Right Case)
c) y is right child of z and x is right child of y (Right Right Case)
d) y is right child of z and x is left child of y (Right Left Case)

Following are the operations to be performed in above mentioned 4 cases. In all of the cases, we only need to re-balance the subtree rooted with z and the complete tree becomes balanced as the height of subtree (After appropriate rotations) rooted with z becomes same as it was before insertion.

### a) Left Left Case

T1, T2, T3 and T4 are subtrees.
z                                      y
/ \                                   /   \
y   T4      Right Rotate (z)          x      z
/ \          - - - - - - - - ->      /  \    /  \
x   T3                               T1  T2  T3  T4
/ \
T1   T2

### b) Left Right Case

     z                               z                           x
/ \                            /   \                        /  \
y   T4  Left Rotate (y)        x    T4  Right Rotate(z)    y      z
/ \      - - - - - - - - ->    /  \      - - - - - - - ->  / \    / \
T1   x                          y    T3                    T1  T2 T3  T4
/ \                        / \
T2   T3                    T1   T2

### c) Right Right Case

  z                                y
/  \                            /   \
T1   y     Left Rotate(z)       z      x
/  \   - - - - - - - ->    / \    / \
T2   x                     T1  T2 T3  T4
/ \
T3  T4

### d) Right Left Case

   z                            z                            x
/ \                          / \                          /  \
T1   y   Right Rotate (y)    T1   x      Left Rotate(z)   z      y
/ \  - - - - - - - - ->     /  \   - - - - - - - ->  / \    / \
x   T4                      T2   y                  T1  T2  T3  T4
/ \                              /  \
T2   T3                           T3   T4

### C implementation

Following is the C implementation for AVL Tree Insertion. The following C implementation uses the recursive BST insert to insert a new node. In the recursive BST insert, after insertion, we get pointers to all ancestors one by one in bottom up manner. So we don’t need parent pointer to travel up. The recursive code itself travels up and visits all the ancestors of the newly inserted node.
1) Perform the normal BST insertion.
2) The current node must be one of the ancestors of the newly inserted node. Update the height of the current node.
3) Get the balance factor (left subtree height – right subtree height) of the current node.
4) If balance factor is greater than 1, then the current node is unbalanced and we are either in Left Left case or left Right case. To check whether it is left left case or not, compare the newly inserted key with the key in left subtree root.
5) If balance factor is less than -1, then the current node is unbalanced and we are either in Right Right case or Right Left case. To check whether it is Right Right case or not, compare the newly inserted key with the key in right subtree root.

#include <stdio.h>
#include <stdlib.h>

// An AVL tree node
struct node {
int key;
struct node *left;
struct node *right;
int height;
};

// A utility function to get maximum of two integers
int max(int a, int b) {
return (a > b) ? a : b;
}

// A utility function to get height of the tree
int height(struct node *N) {
if (N == NULL) {
return 0;
}
return N->height;
}

/* Helper function that allocates a new node with the given key and
NULL left and right pointers. */
struct node *newNode(int key) {
struct node *node = (struct node *)
malloc(sizeof(struct node));
node->key = key;
node->left = NULL;
node->right = NULL;
node->height = 1;   // new node is initially added at leaf
return node;
}

/*
* T1, T2 and T3 are subtrees of the tree rooted with y (on left side)
* or x (on right side)
*               y                               x
*              / \     Right Rotation          /  \
*             x   T3   – – – – – – – >        T1   y
*            / \       < - - - - - - -            / \
*           T1  T2     Left Rotation            T2  T3
* Keys in both of the above trees follow the following order
*     keys(T1) < key(x) < keys(T2) < key(y) < keys(T3)
* So BST property is not violated anywhere.
*
*/

// A utility function to right rotate subtree rooted with y
// See the diagram given above
struct node *rightRotate(struct node *y) {
struct node *x = y->left;
struct node *T2 = x->right;

// Perform rotation
x->right = y;
y->left = T2;

// Update heights
y->height = max(height(y->left), height(y->right)) + 1;
x->height = max(height(x->left), height(x->right)) + 1;

// Return new root
return x;
}

/*
* T1, T2 and T3 are subtrees of the tree rooted with y (on left side)
* or x (on right side)
*               y                               x
*              / \     Right Rotation          /  \
*             x   T3   – – – – – – – >        T1   y
*            / \       < - - - - - - -            / \
*           T1  T2     Left Rotation            T2  T3
* Keys in both of the above trees follow the following order
*     keys(T1) < key(x) < keys(T2) < key(y) < keys(T3)
* So BST property is not violated anywhere.
*
*/

// A utility function to left rotate subtree rooted with x
// See the diagram above
struct node *leftRotate(struct node *x) {
struct node *y = x->right;
struct node *T2 = y->left;

// Perform rotation
y->left = x;
x->right = T2;

// Update heights
x->height = max(height(x->left), height(x->right)) + 1;
y->height = max(height(y->left), height(y->right)) + 1;

// Return new root
return y;
}

// Get Balance factor of node N
int getBalance(struct node *N) {
if (N == NULL) {
return 0;
}
return height(N->left) - height(N->right);
}

struct node *insert(struct node *node, int key) {
/* 1.   Perform the normal BST rotation */
// 递归基，树空或者找到插入位置
if (node == NULL) {
return newNode(key);
}

if (key < node->key) {
node->left = insert(node->left, key);
} else {
node->right = insert(node->right, key);
}

// 递归返回前，只有可能走以上三个分支

/* 2.   Update height of this ascestor node */
node->height = max(height(node->left), height(node->right)) + 1;

/* 3.   Get the balance factor of this ancestor node to check whether
this node became unbalanced */
int balance = getBalance(node);

// If this node becomes unbalanced, then there are 4 cases

/*
*  a) Left Left Case
*
*  T1, T2, T3 and T4 are subtrees.
*
*            z                                      y
*           / \                                   /   \
*          y   T4      Right Rotate (z)          x      z
*         / \          - - - - - - - - ->      /  \    /  \
*        x   T3                               T1  T2  T3  T4
*       / \
*     T1   T2
*/
if (balance > 1 && key < node->left->key) {
return rightRotate(node);
}

/*
*  b) Right Right Case
*
*    z                                y
*   /  \                            /   \
*  T1   y     Left Rotate(z)       z      x
*      /  \   - - - - - - - ->    / \    / \
*     T2   x                     T1  T2 T3  T4
*         / \
*       T3  T4
*/
if (balance < -1 && key > node->right->key) {
return leftRotate(node);
}

/*
*  c) Left Right Case
*
*        z                               z                           x
*       / \                            /   \                        /  \
*      y   T4  Left Rotate (y)        x    T4  Right Rotate(z)    y      z
*     / \      - - - - - - - - ->    /  \      - - - - - - - ->  / \    / \
*   T1   x                          y    T3                    T1  T2 T3  T4
*       / \                        / \
*     T2   T3                    T1   T2
*/
if (balance > 1 && key > node->left->key)
{
node->left =  leftRotate(node->left);
return rightRotate(node);
}

/*
*  d) Right Left Case
*
*      z                            z                            x
*     / \                          / \                          /  \
*   T1   y   Right Rotate (y)    T1   x      Left Rotate(z)   z      y
*       / \  - - - - - - - - ->     /  \   - - - - - - - ->  / \    / \
*      x   T4                      T2   y                  T1  T2  T3  T4
*     / \                              /  \
*   T2   T3                           T3   T4
*/
if (balance < -1 && key < node->right->key)
{
node->right = rightRotate(node->right);
return leftRotate(node);
}

/* return the (unchanged) node pointer */
return node;
}

// A utility function to print preorder traversal of the tree.
// The function also prints height of every node
void preOrder(struct node *root)
{
if(root != NULL)
{
printf("%d ", root->key);
preOrder(root->left);
preOrder(root->right);
}
}

/* Drier program to test above function*/
int main()
{
struct node *root = NULL;

/* Constructing tree given in the above figure */
root = insert(root, 10);
root = insert(root, 20);
root = insert(root, 30);
root = insert(root, 40);
root = insert(root, 50);
root = insert(root, 25);

/* The constructed AVL Tree would be
30
/  \
20   40
/  \     \
10  25    50
*/

printf("Pre order traversal of the constructed AVL tree is \n");
preOrder(root);

return 0;
}

/**
* Output:
* Pre order traversal of the constructed AVL tree is
*  30 20 10 25 40 50
*/

Time Complexity: The rotation operations (left and right rotate) take constant time as only few pointers are being changed there. Updating the height and getting the balance factor also take constant time. So the time complexity of AVL insert remains same as BST insert which is O(h) where h is height of the tree. Since AVL tree is balanced, the height is O(Logn). So time complexity of AVL insert is O(Logn).

The AVL tree and other self balancing search trees like Red Black are useful to get all basic operations done in O(Logn) time. The AVL trees are more balanced compared to Red Black Trees, but they may cause more rotations during insertion and deletion. So if your application involves many frequent insertions and deletions, then Red Black trees should be preferred. And if the insertions and deletions are less frequent and search is more frequent operation, then AVL tree should be preferred over Red Black Tree.（AVL由于更为平衡，搜索的平均效率会好于红黑树）

# 2 Deletion

struct node* deleteNode(struct node* root, int key)
{
// STEP 1: PERFORM STANDARD BST DELETE
// 递归基1: Tree is NULL
if (root == NULL)
return root;

// If the key to be deleted is smaller than the root's key,
// then it lies in left subtree
if ( key < root->key )
root->left = deleteNode(root->left, key);

// If the key to be deleted is greater than the root's key,
// then it lies in right subtree
else if( key > root->key )
root->right = deleteNode(root->right, key);

// if key is same as root's key, then This is the node
// to be deleted
else
{
// 递归基2: 找到被删除node，且该node是叶子节点或者只有一个孩子        // node with only one child or no child
if( (root->left == NULL) || (root->right == NULL) )
{
struct node *temp = root->left ? root->left : root->right;

// No child case
if(temp == NULL)
{
temp = root;
root = NULL;
}
else // One child case
*root = *temp; // Copy the contents of the non-empty child

free(temp);
}
else
{
// node with two children: Get the inorder successor (smallest
// in the right subtree)
struct node* temp = minValueNode(root->right);

// Copy the inorder successor's data to this node
root->key = temp->key;

// Delete the inorder successor
root->right = deleteNode(root->right, temp->key);
}
}

// If the tree had only one node then return
if (root == NULL)
return root;

// STEP 2: UPDATE HEIGHT OF THE CURRENT NODE
root->height = max(height(root->left), height(root->right)) + 1;

// STEP 3: GET THE BALANCE FACTOR OF THIS NODE (to check whether
//  this node became unbalanced)
int balance = getBalance(root);

// If this node becomes unbalanced, then there are 4 cases

// Left Left Case
if (balance > 1 && getBalance(root->left) >= 0)
return rightRotate(root);

// Left Right Case
if (balance > 1 && getBalance(root->left) < 0)
{
root->left =  leftRotate(root->left);
return rightRotate(root);
}

// Right Right Case
if (balance < -1 && getBalance(root->right) <= 0)
return leftRotate(root);

// Right Left Case
if (balance < -1 && getBalance(root->right) > 0)
{
root->right = rightRotate(root->right);
return leftRotate(root);
}

return root;
}

Time Complexity: The rotation operations (left and right rotate) take constant time as only few pointers are being changed there. Updating the height and getting the balance factor also take constant time. So the time complexity of AVL delete remains same as BST delete which is O(h) where h is height of the tree. Since AVL tree is balanced, the height is O(Logn). So time complexity of AVL delete is O(Logn).

1.

2.

3.

4.

5.

# RB-Tree

Red-Black Tree is a self-balancing Binary Search Tree (BST) where every node follows following rules.

1) Every node has aCOLOR either red or black.

2) Root of tree is always black.

3) There are no two adjacent red nodes (A red node cannot have a red parent or red child).

4) Every path from root to a NULL node has same number of black nodes.

## Comparison with AVL Tree

1. 如果插入一个node引起了树的不平衡，AVL和RB-Tree都是最多只需要2次旋转操作，即两者都是O(1)；但是在删除node引起树的不平衡时，最坏情况下，AVL需要维护从被删node到root这条路径上所有node的平衡性，因此需要旋转的量级O(logN)，而RB-Tree最多只需3次旋转，只需要O(1)的复杂度。

2. 其次，AVL的结构相较RB-Tree来说更为平衡，在插入和删除node更容易引起Tree的unbalance，因此在大量数据需要插入或者删除时，AVL需要rebalance的频率会更高。因此，RB-Tree在需要大量插入和删除node的场景下，效率更高。自然，由于AVL高度平衡，因此AVL的search效率更高。

3. map的实现只是折衷了两者在search、insert以及delete下的效率。总体来说，RB-tree的统计性能是高于AVL的。

## How does a Red-Black Tree ensure balance?

A simple example to understand balancing is, a chain of 3 nodes is not possible in red black tree. We can try any combination ofCOLORS and see all of them violate Red-Black tree property.

From the above examples, we get some idea how Red-Black trees ensure balance. Following is an important fact about balancing in Red-Black Trees.

## Every Red Black Tree with n nodes has height <= 2Log2(n+1)

This can be proved using following facts:

1. 对于一棵普通的二叉树来说，如果从root到leaf的所有path中，节点数最少为k个(例如，如果k等于3，那么n至少等于7)，那么有n >= 2k – 1，可以写成k <= Log2(n+1)。

2. 由该性质“Every path from root to a NULL node has same number of black nodes.”，我们可以推出在一棵有n个节点的红黑树中，root到leaf的所有path中，每一条path最多只可能有Log2(n+1)个黑色节点。（例如log(7+1) = 3, log(4+1) = 2）

3. From property 3 of Red-Black trees, we can claim that the number black nodes in a Red-Black tree is at least ⌊ n/2 ⌋ where n is total number of nodes.（黑节点比红节点多

From above 2 points, we can conclude the fact that Red Black Tree with n nodes has height <= 2Log2(n+1)

## Insertion

In Red-Black tree, we use two tools to do balancing.

1) Recoloring
2) Rotation

Let x be the newly inserted node.
1) Perform
standard BST insertion and make the COLOR of newly inserted nodes as RED.

2) Do following if COLOR of x’s parent is not BLACK or x is not root.
….a) If x’s uncle is RED (Grand parent must have been black from
property 4)
……..(i) Change COLOR
of parent and uncle as BLACK.
……..(ii)
COLOR of grand parent as RED.
……..(iii) Change x = x’s grandparent, repeat steps 2 and 3 for new x.

….b) If x’s uncle is BLACK, then there can be four configurations for x, x’s parent (p) and x’s grandparent (g) (This is similar to AVL Tree)
……..i) Left Left Case (p is left child of g and x is left child of p)
……..ii) Left Right Case (p is left child of g and x is right child of p)
……..iii) Right Right Case (Mirror of case a)
……..iv) Right Left Case (Mirror of case c)

3) If x is root, changeCOLOR of x as BLACK (Black height of complete tree increases by 1).

Following are operations to be performed in four subcases when uncle is BLACK.

#### All four cases when Uncle is BLACK

Left Left Case (See g, p and x)

Left Right Case (See g, p and x)

Right Right Case (See g, p and x)

Right Left Case (See g, p and x)

# Deletion

## Insertion Vs Deletion:

Like Insertion, recoloring and rotations are used to maintain the Red-Black properties.

In insert operation, we checkCOLOR of uncle to decide the appropriate case. In delete operation, we checkCOLOR of sibling to decide the appropriate case.

The main property that violates after insertion is two consecutive reds. In delete, the main violated property is, change of black height in subtrees as deletion of a black node may cause reduced black height in one root to leaf path.

Deletion is fairly complex process.  To understand deletion, notion of double black is used.  When a black node is deleted and replaced by a black child, the child is marked as double black. The main task now becomes to convert this double black to single black.

## Deletion Steps

Following are detailed steps for deletion.

1) Perform standard BST delete. When we perform standard delete operation in BST, we always end up deleting a node which is either leaf or has only one child (For an internal node, we copy the successor and then recursively call delete for successor, successor is always a leaf node or a node with one child). So we only need to handle cases where a node is leaf or has one child. Let v be the node deleted and u be the child that replaces v.

2) Simple Case: If either u or v is red, we mark the replaced child as black (No change in black height). Note that both u and v cannot be red as v is parent of u and two consecutive reds are not allowed in red-black tree.

3) If Both u and v are Black.

3.1)COLOR u as double black.  Now our task reduces to convert this double black to single black. Note that If v is leaf, then u is NULL and color of NULL is considered as black. So the deletion of a black leaf also causes a double black.

3.2) Do following while the current node u is double black or it is not root. Let sibling of node be s.
….(a): If sibling s is black and at least one of sibling’s children is red, perform rotation(s). Let the red child of s be r. This case can be divided in four subcases depending upon positions of s and r.

…………..(i) Left Left Case (s is left child of its parent and r is left child of s or both children of s are red). This is mirror of right right case shown in below diagram.

…………..(ii) Left Right Case (s is left child of its parent and r is right child). This is mirror of right left case shown in below diagram.

…………..(iii) Right Right Case (s is right child of its parent and r is right child of s or both children of s are red)

…………..(iv) Right Left Case (s is right child of its parent and r is left child of s)

…..(b): If sibling is black and its both children are black, perform recoloring, and recur for the parent if parent is black.

In this case, if parent was red, then we didn’t need to recur for prent, we can simply make it black (red + double black = single black)

…..(c): If sibling is red, perform a rotation to move old sibling up, recolor the old sibling and parent. The new sibling is always black (See the below diagram). This mainly converts the tree to black sibling case (by rotation) and  leads to case (a) or (b). This case can be divided in two subcases.
…………..(i) Left Case (s is left child of its parent). This is mirror of right right case shown in below diagram. We right rotate the parent p.
…………..(iii) Right Case (s is right child of its parent). We left rotate the parent p.

3.3) If u is root, make it single black and return (Black height of complete tree reduces by 1).

# 推荐

posted @ 2015-08-10 17:32  Acjx  阅读(1153)  评论(0编辑  收藏  举报