zoukankan      html  css  js  c++  java
  • 树的基本操作

    按先序创建二叉树

    注意:总结java基础错误

    1. 误认为java是可以传递引用的,写的时候把引用传进函数作为形参,然后对其进行修改,最后发现,无论怎么改动,外部引用的值依旧不变。

    2. 所以想要达到获取修改后的引用的效果,正确的做法应该是:在函数中返回修改后的形参引用,然后在调用代码中,获取这个返回的引用,即可!!(因为想达到,把root根结点传进函数中,创建二叉树。结果一直改变不了root)

    3. 栈也是有他独立的空间存储当前的变量值的,如果想要达到递归中 读取一个数组中的数据来创建二叉树,

      那么index数组下标索引要设置为全局变量才可以!

    4. 所以:凡是涉及到在函数内部,想要修改引用(new (),malloc())的情况,在Java中,必须要返回这个新的引用给原调用函数。

      在C语言中,想要修改指针的指向,要用指针的指针

    树 完整代码:

    /**
     * 二叉树
     *
     */
    public class BinaryTree<T> {
        public BinaryTreeNode root;
    
        public static int index = 0;
    
        public BinaryTree(){
    
        }
    
        public BinaryTree(T data) {
            this.root = new BinaryTreeNode(data);
        }
    
        //遍历
    
        //先序遍历
        public void preTraverse(BinaryTreeNode node){
    
            if(node==null){
                return;
            }
    
            System.out.printf("%5s",node.data);
    
            preTraverse(node.lchild);
    
            preTraverse(node.rchild);
        }
    
    
        //一个个地插入太麻烦了,我决定写一个按先序遍历 创建二叉树
        public  BinaryTreeNode preOrderCreateBinaryTree(BinaryTreeNode node,T[] arr) throws IOException {
    
    
            if(arr[index].equals("*")){
                node = null;
                index++;
            } else{
                node = new BinaryTreeNode<T>();
                node.data = arr[index];
    
                index++;
    
                node.lchild = preOrderCreateBinaryTree(node.lchild,arr);
                node.rchild = preOrderCreateBinaryTree(node.rchild,arr);
            }
    
            return node;
        }
    }
    
    
        //一个个地插入太麻烦了,我决定写一个按先序遍历 创建二叉树
        public  BinaryTreeNode preOrderCreateBinaryTree(BinaryTreeNode node,T[] arr) throws IOException {
    
    
            if(arr[index].equals("*")){
                node = null;
                index++;
            } else{
                node = new BinaryTreeNode<T>();
                node.data = arr[index];
    
                index++;
    
                //别忘了设置左右孩子的关联
                node.lchild = preOrderCreateBinaryTree(node.lchild,arr);
                node.rchild = preOrderCreateBinaryTree(node.rchild,arr);
            }
    
            //返回修改后的根节点引用
            return node;
        }
    

    测试:

    String[] arr = {"11","10","8","5","*","*","9","*","*","*","16","12","*","*","18","*","*"};
    String[] arr2 = {"11","10","*","*","12","*","*"};
    BinaryTreeNode node = tree2.preOrderCreateBinaryTree(tree2.root, arr);
    
    
    tree2.preTraverse(node);
    

    测试结果:

    插入结点

    插入结点:

    插入左孩子,如果不存在,则直接插入;如果已存在,则让当前左孩子作为新插入的左孩子的左孩子

    (插入右孩子同理)

    /**
     * 树的结点
     * 1. 插入结点:(插入左孩子,如果不存在,则直接插入;如果已存在,则让当前左孩子作为新插入的左孩子的左孩子) (插入右孩子同理)
     * @param <T>
     */
    public class BinaryTreeNode<T> {
            public BinaryTreeNode lchild;
            public BinaryTreeNode rchild;
            public T data;
    
            public BinaryTreeNode(){
    
            }
    
            public BinaryTreeNode(T data) {
                this.lchild = null;
                this.rchild = null;
                this.data = data;
            }
    
    
        //插入左孩子
            public BinaryTreeNode insertLeft( T data){
                //判断当前有无左孩子
                if(this.lchild==null){
                    this.lchild = new BinaryTreeNode(data);
                }else{  //如果已存在,则让当前左孩子作为新插入的左孩子的左孩子)
                    BinaryTreeNode oldNode = this.lchild;       //保存当前左孩子
                    BinaryTreeNode newNode = new BinaryTreeNode(data);
                    this.lchild = newNode;
                    newNode.lchild = oldNode;
                }
    
                return this.lchild;
            }
    
        //插入右孩子
            public BinaryTreeNode insertRight(T data){
                if(this.rchild==null){
                    this.rchild = new BinaryTreeNode(data);
                }else{
                    BinaryTreeNode oldNode = this.rchild;
                    BinaryTreeNode newNode = new BinaryTreeNode(data);
                    this.rchild = newNode;
                    newNode.rchild = oldNode;
                }
                return this.rchild;
            }
    }
    

    结果:

    /*
    *   构造 (按从左到右,层序)
    *       11
    *    8       16
    *  5   9   12  18
    *  要在11的左边插入10
    *
    *       11
    *     10  16
    *    8   12  18
    *   5  9
    *
    * */
    

    测试:

            BinaryTree<Integer> tree = new BinaryTree<Integer>(11);
    
            BinaryTreeNode a_node = tree.root;
    
            BinaryTreeNode b_node = a_node.insertLeft(8);
    
            BinaryTreeNode c_node = a_node.insertRight(16);
    
            BinaryTreeNode d_node = b_node.insertLeft(5);
    
            BinaryTreeNode f_node = b_node.insertRight(9);
    
            BinaryTreeNode g_node = c_node.insertLeft(12);
    
            BinaryTreeNode h_node = c_node.insertRight(18);
    
            tree.preTraverse(tree.root);
    
            //插入10
            a_node.insertLeft(10);
    
            System.out.println();
    
            tree.preTraverse(tree.root);
    

    结果:

    深度优先遍历

    //先序遍历
    public void preTraverse(BinaryTreeNode node){
    
        if(node==null){
            return;
        }
    
        System.out.printf("%5s",node.data);
    
        preTraverse(node.lchild);
    
        preTraverse(node.rchild);
    }
    

    中序,后序同理,用递归实现!

    中序

        public void inTraverse(BinaryTreeNode node){
            if(node==null){
                return;
            }
    
            inTraverse(node.lchild);
    
            System.out.printf("%5s",node.data);
    
            inTraverse(node.rchild);
        }
    
    
    

    后序:

        public void afterTraverse(BinaryTreeNode node){
            if(node==null){
                return;
            }
    
            afterTraverse(node.lchild);
            afterTraverse(node.rchild);
            System.out.printf("%5s",node.data);
        }
    

    广度优先遍历

    即层序遍历

        //层序遍历
        public void levelTraverse(BinaryTreeNode node) throws Exception {
            CycleQueue queue = new CycleQueue(new BinaryTreeNode[100]);
            queue.enQueue(node);     //初始化,保存根结点
    
            while (!queue.isEmpty()){
                BinaryTreeNode current = (BinaryTreeNode) queue.deQueue();
                System.out.printf("%5s",current.data);        //出队
    
                if(current.lchild!=null){
                    queue.enQueue(current.lchild);
                }
    
                if(current.rchild!=null){
                    queue.enQueue(current.rchild);
                }
            }
        }
    

    总结:

    思路:想要做到按层序输出,首先我们发现,层序,是按根 左边孩子,右边孩子,再输出上一个左孩子的左孩子,再输出上一个右孩子的右孩子。

    也就是我们在输出的时候,要保存住上一个访问过的左孩子结点,把他们的孩子存储下来,以便以后按序输出

    (借助队列来保存,FIFO的特性可以完成这一点:保存将来要输出的左孩子,右孩子,并按序输出)

    图:

    其实:层序:1-2-5-3-4-6-7

    我们可以想象成,这个顺序是一条直线,是线性结构:并且先进入的先输出(FIFO)--->并且访问过的要去掉--->

    队列

  • 相关阅读:
    Linux监控平台、安装zabbix、修改zabbix的admin密码
    LVS DR模式搭建、keepalived+lvs
    负载均衡集群相关、LVS介绍、LVS调度算法、LVS NAT模式搭建
    集群相关、用keepalived配置高可用集群
    mysql基础
    MySQL主从、环境搭建、主从配制
    Tomcat配置虚拟主机、tomcat的日志
    Tomcat介绍、安装jdk、安装Tomcat、配置Tomcat监听80端口
    FTP相关、用vsftpd搭建ftp、xshell使用xftp传输文件、使用pure-ftpd搭建ftp服务
    HTTP Status 500
  • 原文地址:https://www.cnblogs.com/zhanp/p/10932652.html
Copyright © 2011-2022 走看看