【數據結構】排序二叉樹

public class SortedBinTree<T extends Comparable> {

    static class Node {
        Object data;
        Node parent;
        Node left;
        Node right;
        public Node(Object data, Node parent, Node left, Node right) {
            this.data = data;
            this.parent = parent;
            this.left = left;
            this.right = right;
        }
        public String toString() {
            return "[data=" + data + "]";
        }
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj.getClass() == Node.class) {
                Node target = (Node)obj;
                return data.equals(target.data)
                        && left == target.left
                        && right == target.right
                        && parent == target.parent;
            }
        }
    }
    private Node root;

    public SortedBinTree() {
        this.root = null;
    }

    public SortedBinTree(T o) {
        this.root = new Node(o, null, null, null);
    }

    /**
     *  新增節點
     * (1)以根節點爲當前節點開始搜索
     * (2)拿新節點的值和當前節點的值比較
     * (3)若是新節點的值更大,則以當前節點的右子節點做爲新的當前節點;不然以當前節點的左子節點做爲新的當前節點。
     * (4)重複(2),(3)兩個步驟,直到搜索到合適的葉子節點。
     * (5)將新節點添加爲第(4)步找到的葉子節點的子節點,若是新節點更大,
     *      則添加爲右子節點;不然,加爲左子節點。
     */
    public void add(T ele) {
        if (root == null) {
            root = new Node(ele, null, null, null);
        } else {
            Node current = root;
            Node parent  = null;
            int cmp = 0;
            do {
                parent = current;
                cmp = ele.compareTo(current.data);
                if (cmp > 0) {
                    current = current.right;
                } else {
                    current = current.left;
                }
            } while (current != null);
            Node newNode = new Node(ele, parent, null, null);
            if (cmp > 0) {
                parent.right = newNode;
            } else {
                parent.left = newNode;
            }
        }
    }

    /**
     *   刪除節點
     *  (1)被刪除的節點是葉子節點:只需將它從其父節點中刪除。
     *
     *  (2)被刪除節點p(非根節點)只有左子樹:若被刪除節點p是其父節點的右子樹,則讓p的左子樹pL添加成p的父節點的右子樹;
     *      被刪除節點p是其父節點的左子樹,則讓p的左子樹pL添加成p的父節點的左子樹。
     *
     *  (3)被刪除節點p(非根節點)只有右子樹:若被刪除節點p是其父節點的右子樹,則讓p的右子樹pR添加成p的父節點的右子樹;
     *      被刪除節點p是其父節點的左子樹,則讓p的右子樹pR添加成p的父節點的左子樹。
     *
     *  (4)若被刪除節點p的左、右子樹均非空,處理方式有兩種
     *      a、將pL設爲p的父節點q的左或右子節點(取決於p是其父節點q的左、右子節點),將pR設爲p節點的中序前趨節點s的右子節點
     *      (s是pL最右下的節點,也就是pL子樹中最大的節點)
     *      b、以p節點的中序前趨或後繼替代p所指節點,而後在從原排序二叉樹中刪去中序前趨或後繼節點。
     *      (即用大於p的最小節點或小於p的最大節點代替p節點)
     */
    public void remove(T ele) {
        Node target = getNode(ele);
        if (target == null) {
            return;
        }

        if (target.left == null && target.right == null) { // 左、右子樹爲空
            if (target == root) {
                root = null;
            } else {
                if (target == target.parent.left) {
                    target.parent.left = null;
                } else {
                    target.parent.right = null;
                }
                target.parent = null;
            }
        } else if (target.left == null && target.right != null) { // 左子樹爲空,右子樹不爲空
            if (target == root) {
                root = target.right;
            } else {
                if (target == target.parent.left) {
                    // 讓target的父節點的left指向target的右子樹
                    target.parent.left = target.right;
                } else {
                    // 讓target的父節點的right指向target的右子樹
                    target.parent.right = target.right;
                }
                // 讓target的右子樹的parent指向target的parent
                target.right.parent = target.parent;
            }
        } else if (target.left != null && target.right == null) { // 左子樹不爲空,右子樹爲空
            if (target == root) {
                root = target.left;
            } else {
                if (target == target.parent.left) {
                    // 讓target的父節點的left指向target的左子樹
                    target.parent.left = target.left;
                } else {
                    // 讓target的父節點的right指向target的左子樹
                    target.parent.right = target.left;
                }
                // 讓target的左子樹的parent指向target的parent
                target.left.parent = target.parent;
            }
        } else if (target.left != null && target.right != null) { // 左、右子樹不爲空
            // leftMaxNode用於保存target節點的左子樹中值最大的節點
            Node leftMaxNode = target.left;
            while (leftMaxNode.right != null) {
                leftMaxNode = leftMaxNode.right;
            }
            // 從原來子樹中刪除leftMaxNode節點
            leftMaxNode.parent.right = null;
            // 讓leftMaxNode的parent指向target的parent
            leftMaxNode.parent = target.parent;
            if (target == target.parent.left) {
                // 讓target的父節點的left指向leftMaxNode
                target.parent.left = leftMaxNode;
            } else {
                // 讓target的父節點的right指向leftMaxNode
                target.parent.right = leftMaxNode;
            }
            leftMaxNode.left = target.left;
            leftMaxNode.right = target.right;
            target.parent = target.left = target.right = null;
        }
    }

    // 根據給定的值搜索節點
    public Node getNode(T ele) {
        Node p = root;
        while (p != null) {
            int cmp = ele.compareTo(p.data);
            if (cmp < 0) {
                p = p.left;
            } else if (cmp > 0) {
                p = p.right;
            } else {
                return p;
            }
        }
        return null;
    }

    // 廣度優先遍歷
    public List<Node> breadthFirst() {
        Queue<Node> queue = new ArrayDeque<Node>();
        List<Node> list = new ArrayList<Node>();
        if (root != null) {
            // 將根元素加入"隊列"
            queue.offer(root);
        }
        while (!queue.isEmpty()) {
            list.add(queue.peek());
            Node p = queue.poll();
            if (p.left != null) {
                queue.offer(p.left);
            }
            if (p.right != null) {
                queue.offer(p.right);
            }
        }
        return list;
    }
}
相關文章
相關標籤/搜索