📜  红黑树|自顶向下插入

📅  最后修改于: 2021-05-24 22:47:17             🧑  作者: Mango

在自下而上的红黑树插入中,使用“简单”的二叉搜索树插入,然后在返回根的过程中纠正RB-Tree违规。借助递归可以很容易地做到这一点。在“自上而下插入”中,在将树向下遍历到插入点的同时进行了更正。实际插入完成后,无需进行任何更正,因此无需遍历树。

因此,“自上而下”插入的目标是以保持RB属性的方式从根部遍历到插入点。因此,这种迭代方法使自上而下的插入比自下而上的插入更快。

用于解决违规和平衡的两个基本操作是-

  • 重新着色
  • 回转

    以下是详细的算法
    该算法的主要目标是创建一个插入点,新节点的父节点在此处为黑色,新节点的叔叔在此处为黑色。

    令N为要插入的新节点。

    1. 如果Y和Z为黑色:

      执行简单的BST插入。插入新节点N作为Y或Z的左/右子节点,并使新插入的节点的颜色为红色。

    2. 如果X的父母是黑人:


      然后为X,Y,Z重新着色并继续沿树下移。

    3. X的父母P是红色,祖父母是黑色,X和P都是祖父母G的左或右子代:

      • 重新着色X,Y,Z
      • 绕G旋转P
      • 颜色P黑色
      • 颜色G红色

      如果存在违规行为,请继续处理其他案件。

    4. X的父母是红色,祖父母是黑色,X和P是祖父母G的对子

      • 重新着色X,Y,Z
      • 将X绕P旋转
      • 绕G旋转X
      • 重新着色X和G

      在所需位置插入新节点N。

      例子 :
      在下面的RB树中插入节点3 –

    下面执行以下方法:

    Java
    // Java implementation for Top-Down
    // Red-Black Tree Insertion creating
    // a red black tree and storing an
    // English sentence into it using Top
    // down insertion approach
      
    import static java.lang.Integer.max;
      
    // Class for performing
    // RBTree operations
    public class RbTree {
        TreeNode Root = null;
      
        // Function to calculate
        // the height of the tree
        int HeightT(TreeNode Root)
        {
            int lefth, righth;
      
            if (Root == null
                || (Root.children == null
                    && Root.children[1] == null)) {
                return 0;
            }
            lefth = HeightT(Root.children[0]);
            righth = HeightT(Root.children[1]);
      
            return (max(lefth, righth) + 1);
        }
      
        // Function to check if
        // dir is equal to 0
        int check(int dir)
        {
            return dir == 0 ? 1 : 0;
        }
      
        // Function to check if a
        // node's color is red or not
        boolean isRed(TreeNode Node)
        {
            return Node != null
                && Node.color.equals("R");
        }
      
        // Function to perform
        // single rotation
        TreeNode SingleRotate(TreeNode Node,
                              int dir)
        {
            TreeNode temp
                = Node.children[check(dir)];
            Node.children[check(dir)]
                = temp.children[dir];
            temp.children[dir] = Node;
            Root.color = "R";
            temp.color = "B";
      
            return temp;
        }
      
        // Function to perform double rotation
        TreeNode DoubleRotate(TreeNode Node,
                              int dir)
        {
            Node.children[check(dir)]
                = SingleRotate(Node.children[check(dir)],
                               check(dir));
            return SingleRotate(Node, dir);
        }
      
        // Function to insert a new
        // node with given data
        TreeNode Insert(RbTree tree,
                        String data)
        {
            if (tree.Root == null) {
                tree.Root
                    = new TreeNode(data);
                if (tree.Root == null)
                    return null;
            }
            else {
      
                // A temporary root
                TreeNode temp = new TreeNode("");
      
                // Grandparent and Parent
                TreeNode g, t;
                TreeNode p, q;
      
                int dir = 0, last = 0;
      
                t = temp;
      
                g = p = null;
      
                t.children[1] = tree.Root;
      
                q = t.children[1];
                while (true) {
      
                    if (q == null) {
      
                        // Inserting root node
                        q = new TreeNode(data);
                        p.children[dir] = q;
                    }
      
                    // Sibling is red
                    else if (isRed(q.children[0])
                             && isRed(q.children[1])) {
      
                        // Recoloring if both
                        // children are red
                        q.color = "R";
                        q.children[0].color = "B";
                        q.children[1].color = "B";
                    }
      
                    if (isRed(q) && isRed(p)) {
      
                        // Resolving red-red
                        // violation
                        int dir2;
                        if (t.children[1] == g) {
                            dir2 = 1;
                        }
                        else {
                            dir2 = 0;
                        }
      
                        // If children and parent
                        // are left-left or
                        // right-right of grand-parent
                        if (q == p.children[last]) {
                            t.children[dir2]
                                = SingleRotate(g,
                                               last == 0
                                                   ? 1
                                                   : 0);
                        }
      
                        // If they are opposite
                        // childs i.e left-right
                        // or right-left
                        else {
                            t.children[dir2]
                                = DoubleRotate(g,
                                               last == 0
                                                   ? 1
                                                   : 0);
                        }
                    }
      
                    // Checking for correct
                    // position of node
                    if (q.data.equals(data)) {
                        break;
                    }
                    last = dir;
      
                    // Finding the path to
                    // traverse [Either left
                    // or right ]
                    dir = q.data.compareTo(data) < 0
                              ? 1
                              : 0;
      
                    if (g != null) {
                        t = g;
                    }
      
                    // Rearranging pointers
                    g = p;
                    p = q;
                    q = q.children[dir];
                }
      
                tree.Root = temp.children[1];
            }
      
            // Assign black color
            // to the root node
            tree.Root.color = "B";
      
            return tree.Root;
        }
      
        // Print nodes at each
        // level in level order
        // traversal
        void PrintLevel(TreeNode root, int i)
        {
            if (root == null) {
                return;
            }
      
            if (i == 1) {
                System.out.print("| "
                                 + root.data
                                 + " | "
                                 + root.color
                                 + " |");
      
                if (root.children[0] != null) {
                    System.out.print(" "
                                     + root.children[0].data
                                     + " |");
                }
                else {
                    System.out.print(" "
                                     + "NULL"
                                     + " |");
                }
                if (root.children[1] != null) {
                    System.out.print(" "
                                     + root.children[1].data
                                     + " |");
                }
                else {
                    System.out.print(" "
                                     + "NULL"
                                     + " |");
                }
      
                System.out.print(" ");
      
                return;
            }
      
            PrintLevel(root.children[0],
                       i - 1);
            PrintLevel(root.children[1],
                       i - 1);
        }
      
        // Utility Function to
        // perform level order
        // traversal
        void LevelOrder(TreeNode root)
        {
            int i;
      
            for (i = 1;
                 i < HeightT(root) + 1;
                 i++) {
                PrintLevel(root, i);
                System.out.print("\n\n");
            }
        }
    }
      
    // Class for representing
    // a node of the tree
    class TreeNode {
      
        // Class variables
        String data, color;
        TreeNode children[];
      
        public TreeNode(String data)
        {
            // Color R- Red
            // and B - Black
            this.data = data;
            this.color = "R";
            children
                = new TreeNode[2];
            children[0] = null;
            children[1] = null;
        }
    }
      
    // Driver Code
    class Driver {
        public static void main(String[] args)
        {
            // Tree Node Representation
            // -------------------------------------------
            // DATA | COLOR | LEFT CHILD | RIGHT CHILD |
            // -------------------------------------------
      
            RbTree Tree = new RbTree();
            String Sentence, Word;
            Sentence = "old is gold";
            String Word_Array[]
                = Sentence.split(" ");
      
            for (int i = 0;
                 i < Word_Array.length;
                 i++) {
                Tree.Root
                    = Tree.Insert(Tree,
                                  Word_Array[i]);
            }
      
            // Print Level Order Traversal
            System.out.println("The Level"
                               + "Order Traversal"
                               + "of the tree is:");
            Tree.LevelOrder(Tree.Root);
            System.out.println("\nInserting a"
                               + " word in the tree:");
            Word = "forever";
            Tree.Root = Tree.Insert(Tree,
                                    Word);
      
            System.out.println("");
            Tree.LevelOrder(Tree.Root);
        }
    }


    C#
    // C# implementation for Top-Down
    // Red-Black Tree Insertion creating
    // a red black tree and storing an
    // English sentence into it using Top
    // down insertion approach
    using System;
      
    // Class for performing
    // RBTree operations
    class RbTree
    {
        public TreeNode Root = null;
      
        // Function to calculate
        // the height of the tree
        public int HeightT(TreeNode Root)
        {
            int lefth, righth;
      
            if (Root == null || 
               (Root.children == null && 
                Root.children[1] == null)) 
            {
                return 0;
            }
            lefth = HeightT(Root.children[0]);
            righth = HeightT(Root.children[1]);
      
            return (Math.Max(lefth, righth) + 1);
        }
      
        // Function to check if
        // dir is equal to 0
        public int check(int dir)
        {
            return dir == 0 ? 1 : 0;
        }
      
        // Function to check if a
        // node's color is red or not
        public bool isRed(TreeNode Node)
        {
            return Node != null && 
                   Node.color.Equals("R");
        }
      
        // Function to perform
        // single rotation
        public TreeNode SingleRotate(TreeNode Node, int dir)
        {
            TreeNode temp = Node.children[check(dir)];
            Node.children[check(dir)] = temp.children[dir];
            temp.children[dir] = Node;
            Root.color = "R";
            temp.color = "B";
      
            return temp;
        }
      
        // Function to perform double rotation
        public TreeNode DoubleRotate(TreeNode Node, int dir)
        {
            Node.children[check(dir)] = 
                 SingleRotate(Node.children[check(dir)], 
                                            check(dir));
            return SingleRotate(Node, dir);
        }
      
        // Function to insert a new
        // node with given data
        public TreeNode Insert(RbTree tree,
                               String data)
        {
            if (tree.Root == null)
            {
                tree.Root = new TreeNode(data);
                if (tree.Root == null)
                    return null;
            }
            else
            {
      
                // A temporary root
                TreeNode temp = new TreeNode("");
      
                // Grandparent and Parent
                TreeNode g, t;
                TreeNode p, q;
      
                int dir = 0, last = 0;
      
                t = temp;
      
                g = p = null;
      
                t.children[1] = tree.Root;
      
                q = t.children[1];
                while (true) 
                {
                    if (q == null) 
                    {
      
                        // Inserting root node
                        q = new TreeNode(data);
                        p.children[dir] = q;
                    }
      
                    // Sibling is red
                    else if (isRed(q.children[0]) && 
                             isRed(q.children[1])) 
                    {
      
                        // Recoloring if both
                        // children are red
                        q.color = "R";
                        q.children[0].color = "B";
                        q.children[1].color = "B";
                    }
      
                    if (isRed(q) && isRed(p)) 
                    {
      
                        // Resolving red-red
                        // violation
                        int dir2;
                        if (t.children[1] == g) 
                        {
                            dir2 = 1;
                        }
                        else 
                        {
                            dir2 = 0;
                        }
      
                        // If children and parent
                        // are left-left or
                        // right-right of grand-parent
                        if (q == p.children[last]) 
                        {
                            t.children[dir2] = 
                              SingleRotate(g, last == 0 ? 1 : 0);
                        }
      
                        // If they are opposite
                        // childs i.e left-right
                        // or right-left
                        else 
                        {
                            t.children[dir2] = 
                              DoubleRotate(g, last == 0 ? 1 : 0);
                        }
                    }
      
                    // Checking for correct
                    // position of node
                    if (q.data.Equals(data)) 
                    {
                        break;
                    }
                    last = dir;
      
                    // Finding the path to
                    // traverse [Either left
                    // or right ]
                    dir = q.data.CompareTo(data) < 0 ? 1 : 0;
      
                    if (g != null) 
                    {
                        t = g;
                    }
      
                    // Rearranging pointers
                    g = p;
                    p = q;
                    q = q.children[dir];
                }
                tree.Root = temp.children[1];
            }
      
            // Assign black color
            // to the root node
            tree.Root.color = "B";
      
            return tree.Root;
        }
      
        // Print nodes at each
        // level in level order
        // traversal
        public void PrintLevel(TreeNode root, int i)
        {
            if (root == null)
            {
                return;
            }
      
            if (i == 1)
            {
                Console.Write("| " + root.data +
                             " | " + root.color + " |");
      
                if (root.children[0] != null) 
                {
                    Console.Write(" " + 
                       root.children[0].data + " |");
                }
                else 
                {
                    Console.Write(" " + "NULL" + " |");
                }
                if (root.children[1] != null)
                {
                    Console.Write(" " + 
                       root.children[1].data + " |");
                }
                else 
                {
                    Console.Write(" " + "NULL" + " |");
                }
      
                Console.Write(" ");
      
                return;
            }
      
            PrintLevel(root.children[0], i - 1);
            PrintLevel(root.children[1], i - 1);
        }
      
        // Utility Function to perform 
        // level order traversal
        public void LevelOrder(TreeNode root)
        {
            int i;
      
            for (i = 1; i < HeightT(root) + 1; i++)
            {
                PrintLevel(root, i);
                Console.Write("\n\n");
            }
        }
    }
      
    // Class for representing
    // a node of the tree
    public class TreeNode 
    {
      
        // Class variables
        public String data, color;
        public TreeNode []children;
      
        public TreeNode(String data)
        {
            // Color R- Red
            // and B - Black
            this.data = data;
            this.color = "R";
            children = new TreeNode[2];
            children[0] = null;
            children[1] = null;
        }
    }
      
    // Driver Code
    public class Driver 
    {
        public static void Main(String[] args)
        {
            // Tree Node Representation
            // -------------------------------------------
            // DATA | COLOR | LEFT CHILD | RIGHT CHILD |
            // -------------------------------------------
            RbTree Tree = new RbTree();
            String Sentence, Word;
            Sentence = "old is gold";
            char[] spearator = { ' ', ' ' }; 
            String []Word_Array = Sentence.Split(spearator, 
                    StringSplitOptions.RemoveEmptyEntries);
      
            for (int i = 0; i < Word_Array.Length; i++)
            {
                Tree.Root = Tree.Insert(Tree,
                                Word_Array[i]);
            }
      
            // Print Level Order Traversal
            Console.WriteLine("The Level" + 
                              "Order Traversal" + 
                              "of the tree is:");
            Tree.LevelOrder(Tree.Root);
            Console.WriteLine("\nInserting a" + 
                              " word in the tree:");
            Word = "forever";
            Tree.Root = Tree.Insert(Tree, Word);
      
            Console.WriteLine("");
            Tree.LevelOrder(Tree.Root);
        }
    }
      
    // This code is contributed by Rajput-Ji


    输出:
    The LevelOrder Traversalof the tree is:
    | is | B | gold | old | 
    
    | gold | R | NULL | NULL | | old | R | NULL | NULL | 
    
    
    Inserting a word in the tree:
    
    | is | B | gold | old | 
    
    | gold | B | forever | NULL | | old | B | NULL | NULL | 
    
    | forever | R | NULL | NULL | 
    

    参考:
    红黑树– UMBC CSEE

    如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。