zoukankan      html  css  js  c++  java
  • Java数据结构与算法(20)

    树的主要算法有插入,查找,显示,遍历,删除,其中显示和删除略微复杂。

    package chap08.tree;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.Stack;
    
    class Node {
    
        public int iData;
        public double dData;
        
        public Node leftChild;
        public Node rightChild;
    
        public void displayNode() {
            System.out.print("{" + iData + ", " + dData + "}");
        }
    }
    
    class Tree {
        
        // first node of tree
        private Node root; 
    
        public Tree() {
            
            root = null;
        } 
    
        /*
         * 查找
         */
        public Node find(int key) { 
            
            // (assumes non-empty tree)
            Node current = root; // start at root
            
            while (current.iData != key) // while no match,
            {
                if (key < current.iData) { 
                    current = current.leftChild;
                }
                else {
                    current = current.rightChild;
                }
                if (current == null) {
                    return null; 
                }
            }
            return current; // found it
        } 
    
        /*
         * 插入
         */
        public void insert(int id, double dd) {
            
            Node newNode = new Node(); // make new node
            newNode.iData = id; // insert data
            newNode.dData = dd;
            
            if (root == null) { // no node in root
                root = newNode;
            }
            else // root occupied
            {
                Node current = root; // start at root
                Node parent;
                
                while (true) // (exits internally)
                {
                    parent = current;
                    if (id < current.iData) {
                        current = current.leftChild;
                        if (current == null) { 
                            // insert on left
                            parent.leftChild = newNode;
                            return;
                        }
                    } 
                    else {
                        current = current.rightChild;
                        if (current == null) { 
                            // insert on right
                            parent.rightChild = newNode;
                            return;
                        }
                    } 
                } 
            } 
        } 
    
        /*
         * 删除
         */
        public boolean delete(int key) 
        { 
            // (assumes non-empty list)
            Node current = root;
            Node parent = root;
            boolean isLeftChild = true;
    
            // search for node
            while (current.iData != key) 
            {
                parent = current;
                if (key < current.iData) // go left?
                {
                    isLeftChild = true;
                    current = current.leftChild;
                } 
                else 
                {
                    isLeftChild = false;
                    current = current.rightChild;
                }
                if (current == null) // end of the line,
                    return false; // didn't find it
            } 
    
            // if no children, simply delete it
            if (current.leftChild == null && current.rightChild == null) {
                if (current == root) {
                    root = null; 
                }
                else if (isLeftChild) {
                    parent.leftChild = null; // disconnect
                }
                else {
                    // from parent
                    parent.rightChild = null;
                }
            }
    
            // if no right child, replace with left subtree
            else if (current.rightChild == null) {
                if (current == root) {
                    root = current.leftChild;
                }
                else if (isLeftChild) {
                    parent.leftChild = current.leftChild;
                }
                else {
                    parent.rightChild = current.leftChild;
                }
            }
    
            // if no left child, replace with right subtree
            else if (current.leftChild == null)
                if (current == root)
                    root = current.rightChild;
                else if (isLeftChild)
                    parent.leftChild = current.rightChild;
                else
                    parent.rightChild = current.rightChild;
    
            // 有两个孩子,则用中序后继替代
            else 
            {
                // get successor of node to delete (current)
                Node successor = getSuccessor(current);
    
                // connect parent of current to successor instead
                if (current == root) {
                    root = successor;
                }
                else if (isLeftChild) {
                    parent.leftChild = successor;
                }
                else {
                    parent.rightChild = successor;
                }
    
                // connect successor to current's left child
                successor.leftChild = current.leftChild;
            } 
            
            return true; 
        } 
    
        /*
         * 获取后继
         * 返回具有倒数第二高的值的节点
         * 找到右孩子,然后右孩子的左子孙
         */
        private Node getSuccessor(Node delNode) {
            
            Node successorParent = delNode;
            Node successor = delNode;
            
            // go to right child
            Node current = delNode.rightChild; 
            
            while (current != null) { 
                successorParent = successor;
                successor = current;
                // go to left child
                current = current.leftChild; 
            }
            
            // if successor not right child
            if (successor != delNode.rightChild) { 
                
                // make connections
                successorParent.leftChild = successor.rightChild;
                successor.rightChild = delNode.rightChild;
            }
            return successor;
        }
    
        public void traverse(int traverseType) {
            switch (traverseType) {
            case 1:
                System.out.print("
    Preorder traversal: ");
                preOrder(root);
                break;
            case 2:
                System.out.print("
    Inorder traversal:  ");
                inOrder(root);
                break;
            case 3:
                System.out.print("
    Postorder traversal: ");
                postOrder(root);
                break;
            }
            System.out.println();
        }
    
        /*
         * 先序遍历
         */
        private void preOrder(Node localRoot) {
            if (localRoot != null) {
                System.out.print(localRoot.iData + " ");
                preOrder(localRoot.leftChild);
                preOrder(localRoot.rightChild);
            }
        }
    
        /*
         * 中序遍历
         */
        private void inOrder(Node localRoot) {
            if (localRoot != null) {
                inOrder(localRoot.leftChild);
                System.out.print(localRoot.iData + " ");
                inOrder(localRoot.rightChild);
            }
        }
    
        /*
         * 后序遍历
         */
        private void postOrder(Node localRoot) {
            if (localRoot != null) {
                postOrder(localRoot.leftChild);
                postOrder(localRoot.rightChild);
                System.out.print(localRoot.iData + " ");
            }
        }
    
        /*
         * 在控制台打印显示树 
         * 
         */
        public void displayTree() {
            
            // 全局栈,初始放入树的根节点
            Stack globalStack = new Stack();
            globalStack.push(root);
            
            // 打印空格的数量
            int nBlanks = 32;
            
            // 是否为空的标识
            boolean isRowEmpty = false;
            
            while (isRowEmpty == false) {
                
                // 本地栈
                Stack localStack = new Stack();
                
                // 设置标识为空,后边再根据实际情况判断其是否不为空
                isRowEmpty = true;
    
                // 打印一定数量的空格,为了将节点 放置在适当的位置以满足视觉效果上树的形状
                for (int j = 0; j < nBlanks; j++) {
                    System.out.print(' ');
                }
    
                while (globalStack.isEmpty() == false) {
                    
                    // 当标识不为空时,从全局栈弹出栈顶节点
                    Node temp = (Node) globalStack.pop();
                    
                    if (temp != null) {
                        // 如果当前从全局栈弹出的栈顶元素 不为空,则打印当前节点数值,同时将其左右孩子节点放入本地栈
                        System.out.print(temp.iData);
                        // 先放左孩子,后方右孩子,后边转移到全局栈后,可以反序,从而保证左孩子在右孩子顶端
                        localStack.push(temp.leftChild);
                        localStack.push(temp.rightChild);
    
                        // 如果当前全局栈弹出的节点有左孩子或右孩子
                        if (temp.leftChild != null || temp.rightChild != null) {
                            // 设置标识不为空
                            isRowEmpty = false;
                        }
                    } 
                    else {
                        // 如果当前从全局栈弹出的栈顶元素 为空,则打印"--"替代节点数值,同时将两个空值放入本地栈
                        System.out.print("-");
                        localStack.push(null);
                        localStack.push(null);
                    }
                    
                    for (int j = 0; j < nBlanks * 2 - 1; j++) {
                        System.out.print(' ');
                    }
                } 
                
                System.out.println();
                System.out.println();
                
                nBlanks /= 2;
                
                while (localStack.isEmpty() == false) {
                    // 将本地栈的节点放入全局栈,进行反序,从而保证先处理左孩子
                    globalStack.push(localStack.pop());
                }
            } 
        } 
    } 
    
    class TreeApp {
        public static void main(String[] args) throws IOException {
            int value;
            Tree theTree = new Tree();
    
            theTree.insert(50, 1.5);
            theTree.insert(25, 1.2);
            theTree.insert(75, 1.7);
            theTree.insert(12, 1.5);
            theTree.insert(37, 1.2);
            theTree.insert(43, 1.7);
            theTree.insert(30, 1.5);
            theTree.insert(33, 1.2);
            theTree.insert(87, 1.7);
            theTree.insert(93, 1.5);
    
            while (true) {
                System.out.print("Enter first letter of show, insert, find, delete, or traverse: ");
    
                int choice = getChar();
                switch (choice) {
                case 's':
                    theTree.displayTree();
                    break;
                case 'i':
                    System.out.print("Enter value to insert: ");
                    value = getInt();
                    theTree.insert(value, value + 0.9);
                    break;
                case 'f':
                    System.out.print("Enter value to find: ");
                    value = getInt();
                    Node found = theTree.find(value);
                    if (found != null) {
                        System.out.print("Found: ");
                        found.displayNode();
                        System.out.print("
    ");
                    } 
                    else {
                        System.out.print("Could not find ");
                    }
                    System.out.print(value + '
    ');
                    break;
                case 'd':
                    System.out.print("Enter value to delete: ");
                    value = getInt();
                    boolean didDelete = theTree.delete(value);
                    if (didDelete) {
                        System.out.print("Deleted " + value + '
    ');
                    }
                    else {
                        System.out.print("Could not delete ");
                    }
                    System.out.print(value + '
    ');
                    break;
                case 't':
                    System.out.print("Enter type 1, 2 or 3: ");
                    value = getInt();
                    theTree.traverse(value);
                    break;
                default:
                    System.out.print("Invalid entry
    ");
                } 
            } 
        } 
    
        /*
         * 获取输入 
         */
        public static String getString() throws IOException {
            InputStreamReader isr = new InputStreamReader(System.in);
            BufferedReader br = new BufferedReader(isr);
            
            String s = br.readLine();
            return s;
        }
    
        public static char getChar() throws IOException {
            String s = getString();
            return s.charAt(0);
        }
    
        public static int getInt() throws IOException {
            String s = getString();
            return Integer.parseInt(s);
        }
    } 
  • 相关阅读:
    IIS和tomcat共用80端口
    CYQ.Data V5 从入门到放弃ORM系列:教程
    C#中==与Equals方法的区别
    一个简单得不能再简单的“ORM”了
    msbuild ConfuserEx.Build 加密
    C#生成注册码
    从多个XML文档中读取数据用于显示webapi帮助文档
    ASP.NET MVC SSO 单点登录设计与实现
    ASP.NET MVC Bootstrap极速开发框架
    Nodejs初阶之express
  • 原文地址:https://www.cnblogs.com/thlzhf/p/4088972.html
Copyright © 2011-2022 走看看