在線生成紅黑樹,刪除節點

博客園拉拉叟提供代碼,在此轉發

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=gbk" />
    <title>在線生成紅黑樹(含變形步驟)</title>

</head>
<body>
    <div>
        <ul>
            <li>增加節點</li>
            <li>方式一:<input type="button" value="隨機增加一個節點" title="隨機增加一個節點" onclick="AddRandom()" /></li>
            <li>方式二:<input id="numbertext" title="" placeholder="請用,(單字節)分割數字,0-999之間的數字" value="" /><input type="button" value="一個一個節點增加" title="增加一個節點" onclick="AddOneNumber()" /></li>
            <li></li>
            <li>刪除節點</li>
            <li><input id="deleteNumberText" type="text" placeholder="請輸入需要刪除的節點" /><input type="button" value="刪除" onclick="DeleteNumber()" /> </li>
            <li></li>
            <li>參考:  http://www.cnblogs.com/skywang12345/p/3603935.html </li>
        </ul>
    </div>
    <form>
        <fieldset>
            <legend>紅黑樹</legend>
            <div id="currentView"></div>
        </fieldset>
    </form>
    <form id="stepView"></form>
 <!--我的博客: http://www.cnblogs.com/bbvi/ --> 
    
    <script>
        var NodeColor = { Black: "black", Red: "red" };

        var RBNode = function (_date, _paret, _color) {
            this.Data = _date;
            this.Parent = _paret;
            this.Color = _color;
            this.LeftNode = null;
            this.RightNode = null;
        }

        var RedBlackBinaryTree = function () {
            this.RootNode = null;//根節點

            this.Insert = function (insertValue) {
                if (this.RootNode == null) {
                    this.RootNode = new RBNode(insertValue, null, NodeColor.Black);
                } else {
                    var newNode = insert.call(this, insertValue);
                    insertFixUp.call(this, newNode);
                }
            }

            function insert(key) {
                ClearStepView();//清空分解步驟
                var node = this.RootNode;

                var newNode = new RBNode(key, null, NodeColor.Red);
                while (true) {
                    if (key > node.Data) {
                        if (node.RightNode == null) {
                            newNode.Parent = node;
                            node.RightNode = newNode;
                            break;
                        }
                        node = node.RightNode;
                    } else if (key < node.Data) {
                        if (node.LeftNode == null) {
                            newNode.Parent = node;
                            node.LeftNode = newNode;
                            break;
                        }
                        node = node.LeftNode;
                    } else {
                        break;
                    }
                }
                return newNode;
            }

            function insertFixUp(node) {
                var parentNode = node.Parent;
                if (parentNode != null && NodeColor.Red == parentNode.Color) {
                    var gprentNode = parentNode.Parent;
                    if (parentNode == gprentNode.LeftNode) {
                        var uncleNode = gprentNode.RightNode;
                        if (uncleNode != null && NodeColor.Red == uncleNode.Color) {
                            CreateStepView(this.RootNode, "insertCaseA1", node.Data);//記錄分解步驟
                            parentNode.Color = NodeColor.Black;
                            uncleNode.Color = NodeColor.Black;
                            gprentNode.Color = NodeColor.Red;
                            CreateStepView(this.RootNode, "insertSolutionA1");//記錄分解步驟
                            insertFixUp.call(this, gprentNode);
                        } else {
                            if (parentNode.RightNode == node) {
                                CreateStepView(this.RootNode, "insertCaseB1", node.Data);//記錄分解步驟
                                leftRotation.call(this, parentNode);
                                CreateStepView(this.RootNode, "insertSolutionB1");//記錄分解步驟
                                insertFixUp.call(this, parentNode);
                            } else if (parentNode.LeftNode == node) {
                                CreateStepView(this.RootNode, "insertCase3", node.Data);//記錄分解步驟
                                parentNode.Color = NodeColor.Black;
                                gprentNode.Color = NodeColor.Red;
                                rightRotation.call(this, gprentNode);
                                CreateStepView(this.RootNode, "insertSolution3");//記錄分解步驟
                            }
                        }
                    } else {
                        var uncleNode = gprentNode.LeftNode;
                        if (uncleNode != null && NodeColor.Red == uncleNode.Color) {
                            CreateStepView(this.RootNode, "insertCaseA1", node.Data);//記錄分解步驟
                            parentNode.Color = NodeColor.Black;
                            uncleNode.Color = NodeColor.Black;
                            gprentNode.Color = NodeColor.Red;
                            CreateStepView(this.RootNode, "insertSolutionA1");//記錄分解步驟
                            insertFixUp.call(this, gprentNode);
                        } else {
                            if (parentNode.LeftNode == node) {
                                CreateStepView(this.RootNode, "insertCase4", node.Data);//記錄分解步驟
                                rightRotation.call(this, parentNode);
                                CreateStepView(this.RootNode, "insertSolution4");//記錄分解步驟
                                insertFixUp.call(this, parentNode);
                            } else if (parentNode.RightNode == node) {
                                CreateStepView(this.RootNode, "insertCase5", node.Data);//記錄分解步驟
                                parentNode.Color = NodeColor.Black;
                                gprentNode.Color = NodeColor.Red;
                                leftRotation.call(this, gprentNode);
                                CreateStepView(this.RootNode, "insertSolution5");//記錄分解步驟
                            }
                        }
                    }
                }
                this.RootNode.Color = NodeColor.Black;
            }

            function leftRotation(node) {
                var temp = node.RightNode;

                node.RightNode = temp.LeftNode;
                if (temp.LeftNode != null) {
                    temp.LeftNode.Parent = node;
                }

                temp.Parent = node.Parent;

                if (node.Parent == null) {
                    this.RootNode = temp;
                }
                else {
                    if (node.Parent.LeftNode == node) {
                        node.Parent.LeftNode = temp;
                    } else {
                        node.Parent.RightNode = temp;
                    }
                }
                temp.LeftNode = node;
                node.Parent = temp;
            }

            function rightRotation(node) {
                var temp = node.LeftNode;

                node.LeftNode = temp.RightNode;
                if (temp.RightNode != null) {
                    temp.RightNode.Parent = node;
                }

                temp.Parent = node.Parent;

                if (node.Parent == null) {
                    this.RootNode = temp;
                } else {
                    if (node == node.Parent.RightNode) {
                        node.Parent.RightNode = temp;
                    } else {
                        node.Parent.LeftNode = temp;
                    }
                }
                temp.RightNode = node;
                node.Parent = temp;
            }

            this.Remove = function (key) {
                var node = search.call(this, this.RootNode, key);
                if (node == null) {
                    return;
                } else {
                    remove.call(this, node);
                }
            }

            function remove(node) {
                ClearStepView();//清空分解步驟
                
                var child, parent, nodeColor;
                if (node.LeftNode != null && node.RightNode != null) {
                    CreateStepView(this.RootNode, "deleteCase8", node.Data);//記錄分解步驟
                    var tempNode = findMin(node.RightNode);
                    if (node.Parent == null) {
                        this.RootNode = tempNode;
                    } else {
                        if (node.Parent.LeftNode == node) {
                            node.Parent.LeftNode = tempNode;
                        } else {
                            node.Parent.RightNode = tempNode;
                        }
                    }

                    child = tempNode.RightNode;
                    parent = tempNode.Parent;
                    nodeColor = tempNode.Color;

                    if (parent.Data == node.Data) {
                        parent = tempNode;
                    } else {
                        if (child != null) {
                            child.Parent = parent;
                        }
                        parent.LeftNode = child;

                        tempNode.RightNode = node.RightNode;
                        node.RightNode.Parent = tempNode;
                    }

                    tempNode.Parent = node.Parent;
                    tempNode.Color = node.Color;
                    tempNode.LeftNode = node.LeftNode
                    node.LeftNode.Parent = tempNode;
                    
                    CreateStepView(this.RootNode, "deleteSolution8");//記錄分解步驟

                    if (nodeColor == NodeColor.Black) {
                        removeFixUp.call(this, child, parent);
                    }
                } else {
                    CreateStepView(this.RootNode, "deleteCase9", node.Data);//記錄分解步驟
                    if (node.LeftNode != null) {
                        child = node.LeftNode;
                    } else {
                        child = node.RightNode;
                    }

                    parent = node.Parent;
                    nodeColor = node.Color;

                    if (child != null) {
                        child.Parent = parent;
                    }

                    if (parent != null) {
                        if (parent.LeftNode != null && parent.LeftNode.Data == node.Data) {
                            parent.LeftNode = child;
                        } else {
                            parent.RightNode = child;
                        }
                    } else {
                        this.RootNode = child;
                    }

                    CreateStepView(this.RootNode, "deleteSolution9");//記錄分解步驟

                    if (nodeColor == NodeColor.Black) {
                        removeFixUp.call(this, child, parent)
                    }
                }
                node = null;
            }

            function removeFixUp(node, parentNode) {
                
                var otherNode;
                while ((node == null || node.Color == NodeColor.Black) && (node != this.RootNode)) {
                    if (parentNode.LeftNode == node) {
                        otherNode = parentNode.RightNode;
                        if (otherNode.Color == NodeColor.Red) {
                            CreateStepView(this.RootNode, "deleteCase1");//記錄分解步驟
                            otherNode.Color = NodeColor.Black;
                            parentNode.Color = NodeColor.Red;
                            leftRotation.call(this, parentNode);
                            otherNode = parentNode.RightNode;
                            CreateStepView(this.RootNode, "deleteSolution1");//記錄分解步驟
                        }

                        if ((otherNode.LeftNode == null || otherNode.LeftNode.Color == NodeColor.Black) &&
                           (otherNode.RightNode == null || otherNode.RightNode.Color == NodeColor.Black)) {
                            CreateStepView(this.RootNode, "deleteCase3");//記錄分解步驟
                            otherNode.Color = NodeColor.Red;
                            node = parentNode;
                            parentNode = node.Parent;
                            CreateStepView(this.RootNode, "deleteSolution3");//記錄分解步驟
                        } else {
                            if (otherNode.RightNode == null || otherNode.RightNode.Color == NodeColor.Black) {
                                CreateStepView(this.RootNode, "deleteCase4");//記錄分解步驟
                                otherNode.LeftNode.Color == NodeColor.Black;
                                otherNode.Color = NodeColor.Red;
                                rightRotation.call(this, otherNode);
                                otherNode = parentNode.RightNode;
                                CreateStepView(this.RootNode, "deleteSolution4");//記錄分解步驟
                            }

                            CreateStepView(this.RootNode, "deleteCase6");//記錄分解步驟
                            otherNode.Color = parentNode.Color;
                            parentNode.Color = NodeColor.Black;
                            otherNode.RightNode.Color = NodeColor.Black;
                            leftRotation.call(this, parentNode);
                            node = this.RootNode;
                            CreateStepView(this.RootNode, "deleteSolution6");//記錄分解步驟
                            break;
                        }
                    } else {
                        otherNode = parentNode.LeftNode;
                        if (otherNode.Color == NodeColor.Red) {
                            CreateStepView(this.RootNode, "deleteCase2");//記錄分解步驟
                            otherNode.Color = NodeColor.Black;
                            parentNode.Color = NodeColor.Red;
                            rightRotation.call(this, parentNode);
                            otherNode = parentNode.LeftNode;
                            CreateStepView(this.RootNode, "deleteSolution2");//記錄分解步驟
                        }

                        if ((otherNode.LeftNode == null || otherNode.LeftNode.Color == NodeColor.Black) &&
                            (otherNode.RightNode == null || otherNode.RightNode.Color == NodeColor.Black)) {
                            CreateStepView(this.RootNode, "deleteCase3");//記錄分解步驟
                            otherNode.Color = NodeColor.Red;
                            node = parentNode;
                            parentNode = node.parent;
                            CreateStepView(this.RootNode, "deleteSolution3");//記錄分解步驟
                        } else {
                            if (otherNode.LeftNode == null || otherNode.LeftNode.Color == NodeColor.Black) {
                                CreateStepView(this.RootNode, "deleteCase5");//記錄分解步驟
                                otherNode.RightNode.Color = NodeColor.Black;
                                otherNode.Color = NodeColor.Red;
                                leftRotation.call(this, otherNode);
                                otherNode = parentNode.LeftNode;
                                CreateStepView(this.RootNode, "deleteSolution5");//記錄分解步驟
                            }
                            CreateStepView(this.RootNode, "deleteCase7");//記錄分解步驟
                            otherNode.Color = parentNode.Color;
                            parentNode.Color = NodeColor.Black;
                            otherNode.LeftNode.Color = NodeColor.Black;
                            rightRotation.call(this, parentNode);
                            node = this.RootNode;
                            CreateStepView(this.RootNode, "deleteSolution7");//記錄分解步驟
                            break;
                        }
                    }
                }
                if (node != null) {
                    node.Color = NodeColor.Black;
                }
            }

            this.Search = function (key) {
                return search.call(this, this.RootNode, key);
            }

            function search(node, key) {
                if (node == null) {
                    return null;
                }

                if (node.Data > key) {
                    return search(node.LeftNode, key);
                } else if (node.Data < key) {
                    return search(node.RightNode, key);
                } else {
                    return node;
                }
            }

            this.FindMin = function () {
                return findMin(this.RootNode);
            }

            function findMin(node) {
                if (node.LeftNode == null) {
                    return node;
                }
                return findMin(node.LeftNode);
            }

            this.FindMax = function () {
                return findMax(this.RootNode)
            }

            function findMax(node) {
                if (node.RightNode == null) {
                    return node;
                }
                return findMax(node.RightNode);
            }


            this.SearchRange = function (minKey, maxKey) {
                return searchRange(minKey, maxKey, this.RootNode, []);
            }

            function searchRange(minKey, maxKey, node, nodeList) {
                if (node == null) {
                    return nodeList;
                }

                if (node.Data > minKey) {
                    searchRange(minKey, maxKey, node.LeftNode, nodeList);
                }

                if (node.Data >= minKey && node.Data < maxKey) {
                    nodeList.push(node.Data);
                }

                if (node.Data < maxKey) {
                    searchRange(minKey, maxKey, node.RightNode, nodeList);
                }

                return nodeList;
            }

            this.LevelOrder = function (action) {
                levelOrder(this.RootNode, action);
            }

            function levelOrder(node, action) {
                var stack = [];
                stack.push(node);

                while (stack.length > 0) {
                    var temp = stack.pop();

                    action(temp);

                    if (temp.LeftNode != null) {
                        stack.push(temp.LeftNode);
                    }

                    if (temp.RightNode != null) {
                        stack.push(temp.RightNode);
                    }
                }
            }


            this.PreOrder = function (action) {
                treeOrder(this.RootNode, action, null, null);
            }

            this.InOrder = function (action) {
                treeOrder(this.RootNode, null, action, null);
            }

            this.PostOrder = function (action) {
                treeOrder(this.RootNode, null, null, action);
            }

            function treeOrder(node, preOrderAction, inOrderAction, postOrderAction) {
                if (preOrderAction) {
                    preOrderAction(node);
                }

                if (node.LeftNode != null) {
                    treeOrder(node.LeftNode, preOrderAction, inOrderAction, postOrderAction);
                }

                if (inOrderAction) {
                    inOrderAction(node);
                }

                if (node.RightNode != null) {
                    treeOrder(node.RightNode, preOrderAction, inOrderAction, postOrderAction);
                }

                if (postOrderAction) {
                    postOrderAction(node);
                }
            }
        }
    </script>

    <script>
        var height = 50;//節點之間的高
        var width = 15;//節點之間的寬
        var tops = 40;//根節點離頂部的距離
        var foot = 40;//樹離底部距離
        var spacing = 30;//樹分別離兩邊的間距

        var tree = new RedBlackBinaryTree();

        function AddOneNumber() {
            var numbertext = document.getElementById("numbertext").value;

            var oneNums = numbertext.match(/[1-9][0-9]{0,2}\,?/);
            document.getElementById("numbertext").value = numbertext.replace(/[1-9][0-9]{0,2}\,?/, "");

            var num = (oneNums + "").match(/[1-9][0-9]{0,2}/);

            if (!!num) {
                AddNumber(parseInt(num));
            }
        }

        function AddRandom() {
            AddNumber(Math.floor(Math.random() * (1000)));
        }

        function AddAllNumber() {
            while (true) {
                AddOneNumber();
                var numbertext = document.getElementById("numbertext").value;
                if (!/[1-9][0-9]{0,2}/.test(numbertext)) {
                    break;
                }
            }
        }

        function AddNumber(number) {
            tree.Insert(number);
            RenewView(tree);
        }

        function DeleteNumber() {
            var deleteNumberText = document.getElementById("deleteNumberText").value;
            if (!deleteNumberText.match(/^[1-9][0-9]{0,2}$/)) {
                alert("請正確輸入1-999的整數");
                return false;
            }
            var number = parseInt(deleteNumberText);
            var isExist = tree.Search(number);
            if (!isExist)
            {
                alert("不存在此節點");
                return false;
            }
            tree.Remove(number);
            document.getElementById("deleteNumberText").value = '';
            RenewView(tree);
        }

        function RenewView(_tree) {
            var currentView = document.getElementById("currentView");
            currentView.innerHTML = '';
            CreateTreeView(_tree.RootNode, currentView);
        }


        function CreateTreeView(rootNode, hostDocument) {
            var size = SetCanvasWidthHeight(rootNode);

            var canvas = document.createElement("canvas");
            canvas.style.backgroundColor = "antiquewhite";
            canvas.style.display = "block";
            canvas.height = size.height;
            canvas.width = size.width;

            var context = canvas.getContext("2d");

            hostDocument.appendChild(canvas);
            SetPoint(rootNode);
            PreOrder(rootNode, SetPreOrder, context, canvas.width);
        }


        function PreOrder(node, action, context, canvasWidth) {
            action(node, context, canvasWidth);

            if (node.LeftNode != null) {
                PreOrder(node.LeftNode, action, context, canvasWidth);
            }

            if (node.RightNode != null) {
                PreOrder(node.RightNode, action, context, canvasWidth);
            }
        }


        function SetCanvasWidthHeight(rootNode) {
            var level = Level(rootNode);
            return {
                height: height * level + tops + foot,
                width: Math.pow(2, level + 1) * width + spacing * 2
            };
        }

        function SetPreOrder(node, context, canvasWidth) {
            var container = drawArc(
                context,
                node.Data,
                canvasWidth / 2 + width * node.nodePoint,
                (node.nodeLevel * height + parseInt(tops)),
                node.Color);

            if (node.Parent != null) {
                var line = linkNode(
                    context,
                    (canvasWidth / 2 + width * node.Parent.nodePoint),
                    (node.Parent.nodeLevel * height + parseInt(tops)),
                    (node.Data, canvasWidth / 2 + width * node.nodePoint),
                    (node.nodeLevel * height + parseInt(tops)));
            }
        }

        //生產節點
        function drawArc(context, number, x, y, color) {
            //圓
            context.beginPath();
            context.fillStyle = color;
            context.arc(x, y, 15, (Math.PI / 180) * 0, (Math.PI / 180) * 360, false);
            context.fill();
            context.closePath();

            //數字
            var textX = x;
            var textY = y + 5;
            if (number < 10) {
                textX -= 5;
            } else if (number > 9 && number < 100) {
                textX -= 8;
            } else {
                textX -= 12;
            }

            context.fillStyle = "white";
            context.font = "bold 15px Arial";
            context.fillText(number + "", textX, textY);
        }

        //鏈接節點
        function linkNode(context, fatherNodeX, fatherNodeY, childrenNodeX, childrenNodeY) {
            drawLine(context, fatherNodeX, fatherNodeY + 15, childrenNodeX, childrenNodeY - 15);
        }

        //生產線
        function drawLine(context, x, y, toX, toY) {
            context.moveTo(x, y);
            context.lineTo(x, y);
            context.lineTo(toX, toY);
            context.stroke();
        }



        var maxLevel;
        var level;
        function Level(rootNode) {
            maxLevel = 0;
            level = 0;
            return levels(rootNode);
        }

        function levels(node) {
            if (node.LeftNode != null) {
                level++;
                levels(node.LeftNode);
            }
            maxLevel = Math.max(maxLevel, level);

            if (node.RightNode != null) {
                level++;
                levels(node.RightNode);
            }
            level--;
            return maxLevel;
        }

        function SetPoint(rootNode) {
            var thisMaxLevel = Level(rootNode);
            var childQuanty = Math.pow(2, thisMaxLevel);

            rootNode.nodeLevel = 0;
            rootNode.nodePoint = 0;

            if (rootNode.LeftNode != null) {
                setPointsLeft(rootNode.LeftNode, -1 * childQuanty / 2, 0, thisMaxLevel - 1);
            }

            if (rootNode.RightNode != null) {
                setPointsRight(rootNode.RightNode, childQuanty / 2, 0, thisMaxLevel - 1);
            }
        }

        function setPointsLeft(node, point, levels, thisMaxLevel) {
            ++levels;
            node.nodeLevel = levels;
            node.nodePoint = point;

            if (node.LeftNode != null) {
                setPointsLeft(node.LeftNode, point - Math.pow(2, thisMaxLevel - levels), levels, thisMaxLevel);
            }

            if (node.RightNode != null) {
                setPointsLeft(node.RightNode, point + Math.pow(2, thisMaxLevel - levels), levels, thisMaxLevel);
            }
        }

        function setPointsRight(node, point, levels, thisMaxLevel) {
            ++levels;
            node.nodeLevel = levels;
            node.nodePoint = point;

            if (node.LeftNode != null) {
                setPointsRight(node.LeftNode, point - Math.pow(2, thisMaxLevel - levels), levels, thisMaxLevel);
            }

            if (node.RightNode != null) {
                setPointsRight(node.RightNode, point + Math.pow(2, thisMaxLevel - levels), levels, thisMaxLevel);
            }
        }


        var stepRemark = {
            "insertCaseA1": {
                "title": "插入節點情況A1",
                "remark": [
                    "當前節點的父節點是紅色,且當前節點的祖父節點的另一個子節點(叔叔節點)也是紅色"
                ]
            },
            "insertSolutionA1": {
                "title": "插入節點情況A1的解決方案",
                "remark": [
                        "(01) 將“父節點”設爲黑色",
                        "(02) 將“叔叔節點”設爲黑色",
                        "(03) 將“祖父節點”設爲“紅色",
                        "(04) 將“祖父節點”設爲“當前節點”(紅色節點);即,之後繼續對“當前節點”進行操作"
                ]
            },
            "insertCaseB1": {
                "title": "插入節點情況2",
                "remark": [
                    "當前節點的父節點是紅色,叔叔節點是黑色,且當前節點是其父節點的右孩子"
                ]
            },
            "insertSolutionB1": {
                "title": "插入節點情況2的解決方案",
                "remark": [
                        "(01) 將“父節點”作爲“新的當前節點”",
                        "(02) 以“新的當前節點”爲支點進行左旋",
                ]
            },
            "insertCase3": {
                "title": "插入節點情況3",
                "remark": [
                    "當前節點的父節點是紅色,叔叔節點是黑色,且當前節點是其父節點的左孩子"
                ]
            },
            "insertSolution3": {
                "title": "插入節點情況3的解決方案",
                "remark": [
                        "(01) 將“父節點”設爲“黑色”",
                        "(02) 將“祖父節點”設爲“紅色”",
                        "(03) 以“祖父節點”爲支點進行右旋"
                ]
            },
            "insertCase4": {
                "title": "插入節點情況4",
                "remark": [
                    "當前節點的父節點是紅色,叔叔節點是黑色,且當前節點是其父節點的左孩子"
                ]
            },
            "insertSolution4": {
                "title": "插入節點情況4的解決方案",
                "remark": [
                        "(01) 將“父節點”作爲“新的當前節點”",
                        "(02) 以“新的當前節點”爲支點進行右旋",
                ]
            },
            "insertCase5": {
                "title": "插入節點情況5",
                "remark": [
                    "當前節點的父節點是紅色,叔叔節點是黑色,且當前節點是其父節點的右孩子"
                ]
            },
            "insertSolution5": {
                "title": "插入節點情況5的解決方案",
                "remark": [
                        "(01) 將“父節點”設爲“黑色”",
                        "(02) 將“祖父節點”設爲“紅色”",
                        "(03) 以“祖父節點”爲支點進行左旋"
                ]
            },
            "deleteCase1": {
                "title": "刪除節點情況1",
                "remark": [
                    "被刪節點是“黑+黑”節點,被刪除的節點是左節點,被刪節點的兄弟節點是紅色。(此時被刪節點的父節點和x的兄弟節點的子節點都是黑節點)。"
                ]
            },
            "deleteSolution1": {
                "title": "刪除節點情況1解決方案",
                "remark": [
                    "(01) 將x的兄弟節點設爲“黑色”。",
                    "(02) 將x的父節點設爲“紅色”。",
                    "(03) 對x的父節點進行左旋。",
                    "(04) 左旋後,重新設置x的兄弟節點。"
                ]
            },
            "deleteCase2": {
                "title": "刪除節點情況2",
                "remark": [
                    "被刪節點是“黑+黑”節點,被刪除的節點是右節點,被刪節點的兄弟節點是紅色。(此時被刪節點的父節點和x的兄弟節點的子節點都是黑節點)。"
                ]
            },
            "deleteSolution2": {
                "title": "刪除節點情況2解決方案",
                "remark": [
                    "(01) 將被刪節點的兄弟節點設爲“黑色”。",
                    "(02) 將被刪節點的父節點設爲“紅色”。",
                    "(03) 對被刪節點的父節點進行右旋。",
                    "(04) 右旋後,重新設置x的兄弟節點。"
                ]
            },
            "deleteCase3": {
                "title": "刪除節點情況3",
                "remark": [
                    "被刪節點是“黑+黑”節點,被刪節點的兄弟節點是黑色,被刪節點的兄弟節點的兩個孩子都是黑色。"
                ]
            },
            "deleteSolution3": {
                "title": "刪除節點情況3解決方案",
                "remark": [
                    "(01) 將被刪節點的兄弟節點設爲“紅色”。",
                    "(02) 設置“被刪節點的父節點”爲“新的被刪節點節點”。"
                ]
            },
            "deleteCase4": {
                "title": "刪除節點情況4",
                "remark": [
                    "將被刪節點是“黑+黑”節點,被刪節點的兄弟節點是黑色;將被刪節點的兄弟節點的左孩子是紅色,右孩子是黑色的。"
                ]
            },
            "deleteSolution4": {
                "title": "刪除節點情況4解決方案",
                "remark": [
                    "(01) 將被刪節點兄弟節點的左孩子設爲“黑色”。",
                    "(02) 將被刪節點兄弟節點設爲“紅色”。",
                    "(03) 對被刪節點的兄弟節點進行右旋。",
                    "(04) 右旋後,重新設置被刪節點的兄弟節點。",
                ]
            },
            "deleteCase5": {
                "title": "刪除節點情況5",
                "remark": [
                    "被刪節點是“黑+黑”節點,被刪節點的兄弟節點是黑色;被刪節點的兄弟節點的左孩子是黑色,右孩子是紅色的。"
                ]
            },
            "deleteSolution5": {
                "title": "刪除節點情況5解決方案",
                "remark": [
                    "(01) 將被刪節點兄弟節點的右孩子設爲“黑色”。",
                    "(02) 將被刪節點兄弟節點設爲“紅色”。",
                    "(03) 對被刪節點的兄弟節點進行左旋。",
                    "(04) 左旋後,重新設置被刪節點的兄弟節點。",
                ]
            },
            "deleteCase6": {
                "title": "刪除節點情況6",
                "remark": [
                    "被刪節點是“黑+黑”節點,被刪節點的兄弟節點是黑色;被刪節點的兄弟節點的右孩子是紅色的,被刪節點的兄弟節點的左孩子任意顏色。"
                ]
            },
            "deleteSolution6": {
                "title": "刪除節點情況6解決方案",
                "remark": [
                    "(01) 將被刪節點父節點顏色 賦值給 被刪節點的兄弟節點。",
                    "(02) 將被刪節點父節點設爲“黑色”。",
                    "(03) 將被刪節點兄弟節點的右子節點設爲“黑色”。",
                    "(04) 對被刪節點的父節點進行左旋。",
                    "(05) 設置“被刪節點”爲“根節點”。"
                ]
            },
            "deleteCase7": {
                "title": "刪除節點情況7",
                "remark": [
                    "被刪節點是“黑+黑”節點,被刪節點的兄弟節點是黑色;被刪節點的兄弟節點的左孩子是紅色的,被刪節點的兄弟節點的右孩子任意顏色。"
                ]
            },
            "deleteSolution7": {
                "title": "刪除節點情況7解決方案",
                "remark": [
                    "(01) 將被刪節點父節點顏色 賦值給 被刪節點的兄弟節點。",
                    "(02) 將被刪節點父節點設爲“黑色”。",
                    "(03) 將被刪節點兄弟節點的左子節設爲“黑色”。",
                    "(04) 對被刪節點的父節點進行右旋。",
                    "(05) 設置“被刪節點”爲“根節點”。"
                ]
            },
            "deleteCase8": {
                "title": "刪除節點情況8",
                "remark": [
                    "被刪節點有兩個子節點"
                ]
            },
            "deleteSolution8": {
                "title": "刪除節點情況8解決方案",
                "remark": [
                    "(01) 將被刪節點右節點的子孫節點中找出小的節點,替換被刪節點。",
                ]
            },
            "deleteCase9": {
                "title": "刪除節點情況9",
                "remark": [
                    "被刪節點只有一個子節點或無子節點"
                ]
            },
            "deleteSolution9": {
                "title": "刪除節點情況9解決方案",
                "remark": [
                    "(01) 將唯一的子節點替換被刪節點。",
                ]
            }
                
        };

        function ClearStepView() {
            var stepView = document.getElementById("stepView");
            stepView.innerHTML = '';
        }

        function CreateStepView(_tree, step, currentNumber) {
            var fieldset = document.createElement("fieldset");
            var legend = document.createElement("legend");
            var ul = document.createElement("ul");
            var canvas = document.createElement("canvas");

            legend.innerHTML = stepRemark[step].title;

            if (!!currentNumber) {
                var li = document.createElement("li");
                li.innerHTML = "當前節點:" + currentNumber;
                ul.appendChild(li);
            }


            for (var i = 0; i < stepRemark[step].remark.length; i++) {
                var li = document.createElement("li");
                li.innerHTML = stepRemark[step].remark[i];
                ul.appendChild(li);
            }

            fieldset.appendChild(legend);
            fieldset.appendChild(ul);
            fieldset.appendChild(canvas);

            var stepView = document.getElementById("stepView");
            stepView.appendChild(fieldset);

            CreateStepTreeView(_tree, canvas);
        }

        function CreateStepTreeView(rootNode, canvas) {
            var size = SetCanvasWidthHeight(rootNode);

            canvas.style.backgroundColor = "antiquewhite";
            canvas.style.display = "block";
            canvas.height = size.height;
            canvas.width = size.width;

            var context = canvas.getContext("2d");

            SetPoint(rootNode);
            PreOrder(rootNode, SetPreOrder, context, canvas.width);
        }
    </script>
</body>
</html>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章