zoukankan      html  css  js  c++  java
  • 树(二叉树的插入删除查找遍历)

    树:由边连着节点而构成
    根:树顶端的节点称为根,一棵树只有一个根
    父节点:每个节点(除了根)都恰好有一条边向上连接到另一个节点,上面的这个节点就称为下面的节点的父节点
    子节点:每个节点都可能有一条或多条向下连接的其他节点,下面的这些节点成为它的子节点
    叶子节点:没有子节点的节点称为叶子节点
    子树:每个节点都可以作为子树的根
    二叉树:每个节点最多只能有两个节点
    查询,插入,删除都很快(跟数组和链表相比)

    public class Node {
        public int iData;//节点值(整数)
        public double dData;//节点值(小数)
        public Node leftChild;//子节点(左)
        public Node rightChild;//子节点(右)
        public void displayNode() {//以{iData,dData}的方式输出值
            System.out.print('{');
            System.out.print(iData);
            System.out.print(',');
            System.out.print(dData);
            System.out.print('}');
        }
    
    }
    import java.util.Stack;
    
    
    public class Tree {
        private Node root;//根节点
        public Tree() {
            root=null;
        }
        //插入值
        public void insert(int id,double dd) {
            Node newNode=new Node();
            newNode.iData=id;
            newNode.dData=dd;
            if(root==null) {
                root=newNode;
            }else {
                Node current=root;//current标志当前节点
                Node parent;//parent标志当前节点发生变化后,之前的current节点就是父节点.
                while(true) {
                    parent=current;
                    if(id<current.iData) {//如果id是小的,就往左边找位置
                        current=current.leftChild;//一直往左边找,循环,直到左边没有找的了
                        if(current==null) {//即找到位置(循环的出口)
                            parent.leftChild=newNode;//插入数据
                            return;
                        }
                    }else {//向右边找
                        current=current.rightChild;
                        if(current==null) {
                            parent.rightChild=newNode;
                            return;
                        }
                        
                    }
                }
            }
        }
        //删除
        public boolean delete(int key) {
            Node current=root;
            Node parent=root;
            boolean isLeftChild=true;
            while(current.iData!=key) {//找节点
                parent=current;
                if(key<current.iData) {
                    isLeftChild=true;
                    current=current.leftChild;
                }else {
                    isLeftChild=false;
                    current=current.rightChild;
                }
                if(current==null) return false;//没找到
                
            }
            
            //删除
            if(current.leftChild==null && current.rightChild==null) {//删除的是叶子结点
                if(current==root)
                    root=null;//删的是根(1)
                else if(isLeftChild) {//删除的是左子叶子
                    parent.leftChild=null;//(2)
                }else {//删除的是右子叶子
                    parent.rightChild=null;//(3)
                }
            }else if(current.rightChild==null) {//删除的节点不是叶子结点,然后删除的是只有左子树
                if(current==root)//(4)
                    root=current.leftChild;//只用将根节点的左子节点标记为root就ok
                else if(isLeftChild)//(5)
                    parent.leftChild=current.leftChild;//如果当前结点是父节点的左子节点,只用将父节点的左子节点标记为当前节点的左子节点
                else //(6)
                    parent.rightChild=current.leftChild;//如果当前节点是父节点的右子节点,只用将父节点的有子节点标记为当前节点的左子节点
                
            }else if(current.leftChild==null) {//要删的节点只有右子树(与上面方法一样)
                if(current==root)//只用将根节点的右子节点标记为root就ok
                    root=current.rightChild;//(7)
                else if(isLeftChild)
                    parent.leftChild=current.rightChild;//(8)
                else parent.rightChild=current.rightChild;//(9)
            }else {//左右子树都有
                Node successor=getSuccessor(current);//寻找继承者
                if(current==root) root=successor;//如果当前结点是根(10)
                else if(isLeftChild)parent.leftChild=successor;//如果当前节点是左子节点(11)
                else parent.rightChild=successor;//(12)
                
                successor.leftChild=current.leftChild;//建立好替换后完整的树
            }
            return true;
            
        }
        //查找
        public Node find(int key) {
            Node current=root;
            while(current.iData!=key) {
                if(key<current.iData) {
                    current=current.leftChild;
                    
                }else {
                    current=current.rightChild;
                }
                if(current==null) {
                    return null;
                }
            }
            return current;
        }
        //遍历(三种方法)
            public void traverse(int traverseType) {
                switch(traverseType){
                    case 1:
                        System.out.print("从上至下,从左至右:");
                        preOrder(root);
                        break;
                    case 2:
                        System.out.print("从下至下,从左至右:");
                        inOrder(root);
                        break;
                    case 3:
                        System.out.print("从下至上,从右至左:");
                        postOrder(root);
                        break;
                        
                        
                }
                System.out.println();
            }
        //找到继承者(树)
        private Node getSuccessor(Node delNode) {
            Node successorParent=delNode;
            Node successor=delNode;//
            Node current=delNode.rightChild;//临时变量
            while(current!=null) {
                successorParent=successor;
                successor=current;
                current=current.leftChild;//找delNode节点的右子树的左子节点
            }
            if(successor!=delNode.rightChild) {//将根为继承者的树建立好
                successorParent.leftChild=successor.rightChild;
                successor.rightChild=delNode.rightChild;
            }//如果是叶子,就不要建立树
            return successor;//返回继承者
        }
        //从上至下,从左至右
        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 dispalyTree() {
            Stack globalStack=new Stack();
            globalStack.push(root);//从这个栈里面要取的输出的值
            int nBlanks=32;//空格数
            boolean isRowEmpth=false;
            //树的开始分割线
            System.out.println("................................");
            while(isRowEmpth==false) {//当输出的节点有子节点时这个循环会继续执行
                Stack localStack=new Stack();//本地栈(存入当前节点的子节点,里面循环结束最后都倒入globalStack中)
                isRowEmpth=true;
                for(int j=0;j<nBlanks;j++)
                    System.out.print(" ");//左边加32个空格
                while(!globalStack.isEmpty()) {//循环输出globalStack栈中的内容,每一次循环都将当前节点的子节点放入本地栈中
                    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)
                            isRowEmpth=false;//如果取出的值有子节点,就继续外层循环(如果当前节点没有子节点就不会进行下一次外层循环)
                    }else {//空的数据项
                        System.out.print("--");
                        localStack.push(null);
                        localStack.push(null);
                    }
                    for(int j=0;j<nBlanks*2-2;j++) {
                        System.out.print(" ");
                    }
                }
                System.out.println();
                nBlanks/=2;
                while(!localStack.isEmpty()) {
                    globalStack.push(localStack.pop());
                }
            }
            //树的结束分割线
            System.out.println("--------------------------------------");
        }
    
    }
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    public class Test {
    
            public static void main(String[] agrs) throws IOException {
                int value;
                Tree theTree=new Tree();
                theTree.insert(50, 1.5);
                theTree.insert(25, 1.5);
                theTree.insert(75, 1.5);
                theTree.insert(12, 1.5);
                theTree.insert(37, 1.5);
                theTree.insert(43, 1.5);
                theTree.insert(30, 1.5);
                theTree.insert(33, 1.5);
                theTree.insert(87, 1.5);
                theTree.insert(93, 1.5);
                theTree.insert(97, 1.5);
                while(true) {
                    System.out.print("Enter first letter of show,isnert,find,delete,or traverse:");
                    int choice=getchar();
                    switch(choice){
                        case's':
                            theTree.dispalyTree();
                            break;
                        case 'i':
                            System.out.print("Enter value to insert:");
                            value=getInt();
                            theTree.insert(value, value+0.9);
                            break;
                        case 'f':
                            System.out.println("Enter value to find:");
                            value=getInt();
                            Node found=theTree.find(value);
                            if(found!=null) {
                                System.out.print("Found :");
                                found.displayNode();
                                System.out.println();
                            }else
                                System.out.print("not"+value);
                            break;
                        case 'd':
                            System.out.print("Enter value todelete:");
                            value=getInt();
                            boolean didDelete=theTree.delete(value);
                            if(didDelete)System.out.print("delete"+value);
                            else System.out.print("not "+value);
                            break;
                        case 't':
                            System.out.print("Enter 1,2 or 3:");
                            value=getInt();
                            theTree.traverse(value);
                            break;
                            default:
                                System.out.println("无效的输入");
                            
                            
                            
                    }
                }
                
            }
            public static String getString()throws IOException{
                InputStreamReader isr=new InputStreamReader(System.in);
                BufferedReader br=new BufferedReader(isr);
                return br.readLine();
                }
            public static char getchar() throws IOException{
                return getString().charAt(0);
                
            }
            public static int getInt() throws IOException{
                String s=getString();
                return Integer.parseInt(s);
            }
    
        }
  • 相关阅读:
    RxJava API使用示例
    使用create-react-app模板模仿12306app
    web 基本概念辨异 —— URI 与 URL
    RESTful 架构与 RESTful 服务
    python startswith和endswith
    python enumerate函数用法
    python中PIL.Image和OpenCV图像格式相互转换
    Linux查看当前在线用户信息
    Linux查看GPU信息和使用情况
    python中的编码和解码
  • 原文地址:https://www.cnblogs.com/S-Mustard/p/7730438.html
Copyright © 2011-2022 走看看