树(二叉树的插入删除查找遍历)

Posted S-Mustard

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树(二叉树的插入删除查找遍历)相关的知识,希望对你有一定的参考价值。

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

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);
        }

    }

 

以上是关于树(二叉树的插入删除查找遍历)的主要内容,如果未能解决你的问题,请参考以下文章

二叉查找树详解

平衡二叉树的操作(高手进)

二叉树

二叉树之二叉搜索树的基本操作实现

数据结构树与树的表示二叉树存储结构及其遍历二叉搜索树平衡二叉树堆哈夫曼树与哈夫曼编码集合及其运算

二叉查找树中元素的删除操作