史上最全二叉树的相关操作:二叉树创建,先中后层序递归非递归等

二叉树基本操作:

导语:你是否还在为不懂如何学好二叉树而发愁,是否还在纠结如何创建构造结点,如何将栈和队列巧妙的结合起来运行程序。徐小渣特对此做以归纳总结,希望能对大家有所帮助。
1.树结点的构造

class BtNode {
public BtNode lchild;//左孩子结点
public BtNode rchild;//右孩子结点
public char data;//存储的数值
public BtNode(BtNode lchild,BtNode rchild){
    this.lchild=lchild;
    this.data=data;
}
public BtNode(char data){
    this.data=data;
}
public BtNode(){}
}

2.二叉树的创建方法
法一:无参构造,向程序中输入内容,此代码默认为输入字符

//二叉树的创建方法
    public static BtNode CreateTree() {
        //char item;
        BtNode s = null;
        Scanner scanner = new Scanner(System.in);
        char item = scanner.next().charAt(0);
        if (item != '#') {
            //s.data=ite`m;
            s = new BtNode(item);
            s.lchild = CreateTree();
            s.rchild = CreateTree();
        }
        return s;
    }

法二:含有参数,参数为提供的字符串和下标

    static class Int {
        private int index;
        public Int() {
            index = 0;
        }
        public Int(int x) {
            index = x;
        }
        int GetIndex() {
            return index;
        }
        void ind() {
            index += 1;
        }
    }
    //利用字符串和下标创建树      注意此处不能用i++
    public static BtNode creat(String s, Int i) {
        // Queue<BtNode> queue= new Queue<>();
        BtNode b = null;
        //int in=i.GetIndex();
        if (s.charAt(i.GetIndex()) != '#') {
            b = new BtNode(s.charAt(i.GetIndex()));
            i.ind();
            b.lchild = creat(s, i);
            i.ind();
            b.rchild = creat(s, i);
        }
        return b;
    }

3.利用递归输出先序,中序,后序:

//先序
    public static void Preorder(BtNode node) {
        if (node != null) {
            System.out.println(node.data);
            Preorder(node.lchild);
            Preorder(node.rchild);
        }
    }
    //中序遍历
    public static void Inorder(BtNode node) {
        if (node != null) {
            Inorder(node.lchild);
            System.out.println(node.data);
            Inorder(node.rchild);
        }
    }
    //后序
    public static void lastorder(BtNode node) {
        if (node != null) {
            Preorder(node.lchild);
            Inorder(node.rchild);
            System.out.println(node.data);
        }
    }

4.利用非递归进行先中后序遍历:(后序相对复杂,小徐在此处采用的方法是设置标志位和栈)

   //先序非递归  利用栈:先进后出
    public static void NicePreOrder(BtNode tree){
      if(tree==null)return;
      Stack<BtNode> stack=new Stack<>();
      stack.push(tree);
      //栈的特征是先进先出,则先把树的右边的入栈后入左边
      while(!stack.empty()){
         BtNode btNode=stack.pop();
          System.out.print(btNode.data+" ");
          if(btNode.rchild!=null) stack.push(btNode.rchild);
          if(btNode.lchild!=null) stack.push(btNode.lchild);
      }
    }


//中序非递归   法一
    public static void NiceInOrder(BtNode tree){
        if(tree==null)return ;
        Stack<BtNode> stack=new Stack<>();
        while(!stack.empty()||tree!=null){
            while (tree!=null){
                stack.push(tree);
                tree=tree.lchild;
            }
            tree=stack.pop();
            System.out.print(tree.data+" ");
            tree=tree.rchild;
        }
    }
    //中序非递归法二
    public static void NiceInOrder2(StkNode tree){
        Stack<StkNode> stack=new Stack<>();
        if(tree ==null) return;
        stack.push(tree);
        while(!stack.empty()){
            StkNode node=stack.pop();
            if(++node.popnum==2){
                System.out.print(node.ptr.data+" ");
            if(node.ptr.rchild!=null){
               stack.push(new StkNode(node.ptr.rchild));
            }
            }else{
                stack.push(node);
                if(node.popnum==1&&node.ptr.lchild!=null){
                    stack.push(new StkNode(node.ptr.lchild));
                }
            }
        }
    }

    // 后序非递归法一
    public static void NiceLOrder(BtNode tree){
     Stack<BtNode> stack=new Stack<>();
     //设置标志位,用来表示右孩子是否输出
     BtNode flag=null;
     while(!stack.empty()||tree!=null){
         while(tree!=null){
             stack.push(tree);
             tree=tree.lchild;
         }
         //此时获取的元素为树最左边的根
         tree=stack.pop();
         //判断其是否有右子树,或者右子树是否被输出过
         //表示无右子树或者已被输出过
         if(tree.rchild==null||tree.rchild==flag){
             System.out.print(tree.data+" ");
             flag=tree;//把标志位转移到tree的位置
             tree=null;
         }
         else{stack.push(tree);
              tree=tree.rchild;
         }
     }
    }

```java
//法二:   后序非递归 
   static class StkNode{
        public BtNode ptr=null;
        public int popnum=0;
        public StkNode(BtNode p){ptr=p;popnum=0;}
}
    public static void NiceLOrder2(StkNode tree){
        Stack<StkNode> stack=new Stack<>();
        if(tree ==null) return;
        stack.push(tree);
        while(!stack.empty()){
            StkNode node=stack.pop();
            if(++node.popnum==3){
                System.out.print(node.ptr.data+" ");
            }else{
                stack.push(node);
                if(node.popnum==1&&node.ptr.lchild!=null){
                    stack.push(new StkNode(node.ptr.lchild));
                }
                else if(node.popnum==2&&node.ptr.rchild!=null){
                    stack.push(new StkNode(node.ptr.rchild));
                }
            }
        }
    }

**5.层序遍历:**
```java
//层序遍历   队的特点:先进先出
    public static void NiceLevelOrder(BtNode tree){
        Queue<BtNode> queue=new LinkedList<>();
         queue.offer(tree);
         while(!queue.isEmpty()){
             tree=queue.poll();
             System.out.print(tree.data+" ");
             //先入左边后入右边
             if(tree.lchild!=null)queue.offer(tree.lchild);
             if(tree.rchild!=null)queue.offer(tree.rchild);
         }
    }

6-7.已知先序和中序的输出结果,求原始二叉树:
(思路与下文七思路一致,有递归思想)
以该题为例:分析先序和中序的特点,先序的输出的第一个即为树的根,在中序的输出结果找到和他一致的元素,返回该下标,则以中序来说,可将其输出结果分为两部分,左边为根节点的左子树,右边为根节点的右子树,先序同理,找到上文提到的下标,则左子树为从根节点的下一个开始到该下标的元素,右节点为剩下所有的元素。在进行划分,利用递归思想即可解题。
查找下标代码:

/先查找对应的下标
    private static int search(String s,char value){
      int pos=-1;
        for (int i = 0; i < s.length(); i++) {
            if(s.charAt(i)==value) {pos=i;break;}
        }
        return pos;
    }

已知先序和中序的输出结果,求原始二叉树

 //  pstr  先序排列的字符串   istr的字符串  n所含元素个数
    private static BtNode CreatPI(String pstr, String istr, int n) {
        if(pstr!=null&&istr!=null) {
            BtNode s = new BtNode(pstr.charAt(0));;
            if (n > 0) {
                int pos = search(istr, s.data);
                if(pos==-1)return null;
                s.lchild = CreatPI(pstr.substring(1, pos + 1), istr.substring(0, pos), n);
                s.rchild = CreatPI(pstr.substring(pos + 1), istr.substring(pos + 1), n - pos - 1);
            }
            return s;
        }
        return null;
    }

已知中序和后序的输出结果,求原始二叉树

    //已知中序 后序 求原始二叉树
    private static BtNode CreatIL(String istr,String lstr,int n) {
        if (istr != null && lstr != null) {
            BtNode s = null;
            if (n > 0) {
                s = new BtNode(lstr.charAt(lstr.length() - 1));
                int pos = search(istr, lstr.charAt(lstr.length() - 1));
                if(pos==-1)return null;
                s.lchild = CreatIL(istr.substring(0, pos), lstr.substring(0, pos), pos);
                s.rchild = CreatIL(istr.substring(pos + 1), lstr.substring(pos, n - 1), n - pos - 1);
            }
            return s;
        }
        return null;
    }

写出k行的全部数值


    public static void Printk(BtNode ptr,int k){
        if(ptr==null||k<0)return;
        if(ptr!=null&&k==0){
            System.out.print(ptr.data+" ");
        }
        else if(ptr!=null){
            Printk(ptr.lchild,k-1);
            Printk(ptr.rchild,k-1);
        }
    }

获取节点个数 分治策略思想

   //获取节点个数   分治策略思想
    public static int Getsize(BtNode tree){
        if(tree==null) return 0;
        else return Getsize(tree.lchild)+Getsize(tree.rchild)+1;
    }

获取深度

//获取深度
public static int GetDepth(BtNode tree){
        if(tree==null) return 0;
        else  return Math.max(GetDepth(tree.lchild),GetDepth(tree.rchild))+1;
}

在树中查找某值是否存在

//在树中查找某值是否存在
public static  boolean FindValue(BtNode tree,char c){
        if(tree==null) return false;
    boolean flag=false;
       if(tree.data==c) return true;
        else {
            if(tree.lchild!=null) flag=FindValue(tree.lchild,c);
            else if(tree.rchild!=null) flag=FindValue(tree.rchild,c);
       }
       return flag;
}

获取双亲节点

//获取双亲
public static BtNode GetParent(BtNode tree,BtNode child) {
    if (child == null || tree == null || tree == child) return null;
    if ((tree.lchild != null && tree.lchild == child) || (tree.rchild != null && tree.rchild == child)) {
        return tree;
    } else if (tree.lchild != null) {
        tree = GetParent(tree.lchild, child);
        if (tree == null) {
            tree = GetParent(tree.rchild, child);
        }
    }
    return tree;
}

判断是否是满二叉树 要么树为空 要么树的左子树为满同时树的右子树为满且两者高度相同

//判断是否是满二叉树  要么树为空 要么树的左子树为满同时树的右子树为满且两者高度相同
public boolean IsFull(BtNode p){
        return (p==null||(IsFull(p.lchild)&&IsFull(p.rchild)&&(GetDepth(p.lchild)==(GetDepth(p.rchild)))));
}

判断是否是满二叉树

//判断是否是满二叉树
public boolean Is_Full(BtNode tree){
        Queue<BtNode> queue=new LinkedList<>();
        int n=1;
        boolean res=true;
        if(tree==null) return  res;
        queue.offer(tree);
        while(!queue.isEmpty()){
            if(queue.size()<n){
                res=false;
                break;
            }
            for (int i = 0; i < n; i++) {
                BtNode p=queue.poll();
                if(p.lchild!=null){
                    queue.offer(p.lchild);
                }
                if(p.rchild!=null){
                    queue.offer(p.rchild);
                }
            }
            n+=n;
        }
        return res;
}

判断是否是完全二叉树

//  判断是否是完全二叉树
public static boolean Is_ComTree(BtNode tree) {
    boolean res = true;
    if (tree == null) return res;
    Queue<BtNode> queue = new LinkedList<>();
    queue.offer(tree);
    while (!queue.isEmpty()) {
        tree = queue.poll();
        if (tree == null) break;
        queue.offer(tree.lchild);
        queue.offer(tree.rchild);
    }
    while (!queue.isEmpty()) {
        tree = queue.poll();
        if (tree != null) {
            res = false;
            break;
        }
    }
    return res;
}

对数组进行中序操作 递归操作

//对数组进行中序操作  递归操作
public static void Inorder_arr(int[] arr,int i,int end){
        if(i<=end&&arr[i]!=-1){
            Inorder_arr(arr,2*i+1,end);
            System.out.print(arr[i]+" ");
            Inorder_arr(arr,2*i+2,end);
        }
}

非递归操作

//非递归操作
public static void NiceInorder_arr(int[] arr){
        if(arr.length<=0)return;
        Stack<Integer> stack=new Stack<>();
        int i=0,end=arr.length-1;
        while((i<=end&&arr[i]!=-1)||!stack.empty()){
            while(i<=end&&arr[i]!=-1){
                stack.push(i);
                i=i*2+1;
            }
            i=stack.pop();
            System.out.print(arr[i]+" ");
            i=2*i+2;
        }
}

链式存储二叉树 将数组转换成链表的形式

public static BtNode CreatAr(int[] arr,int index){
        BtNode tree=null;
        if(index<arr.length-1&&arr[index]!=-1) {
            tree = new BtNode(arr[index]);
             tree.lchild=CreatAr(arr,index+1);
             tree.rchild=CreatAr(arr,index+1);
        }
        return tree;
}

将中序遍历转换为双向链表

//  将中序遍历转换为双向链表
public static void inoder(BtNode tree) {
        BtNode pre=null;
        BtNode ptr=tree;
    if (tree == null) return;
    Stack<BtNode> stack = new Stack<>();
    while (!stack.empty()||ptr!=null) {
        while (ptr != null) {
            stack.push(ptr);
            ptr=ptr.lchild;
        }
        ptr = stack.pop();
       if(pre==null){
           pre=ptr;
           tree=ptr;
       }
       else {
           pre.rchild=ptr;
           ptr.lchild=pre;
           pre=ptr;
       }
       ptr=ptr.rchild;
    }
}

主函数调用:

 public static void main(String[] args) {
        Int i=new Int(0);
        BtNode node= creat("abc####",i);
      //  System.out.print(node.data);
       // BtNode x=CreateTree();
      // Preorder(node);
        //lastorder(node);
        BtNode node1=new BtNode();
      //  String pstr="abdecfg";
        String istr="dbeafcg";
        String lstr="debfgca";
        //String istr="badc";
        //String lstr="bdca";
       node1=CreatIL(istr,lstr,7);
       // Preorder(node1);
       // NiceInOrder(node1);
        //NiceLOrder1(node1);
        //NiceLevelOrder(node1);
        StkNode node2=new StkNode(node1);
  //      NiceLOrder2(node2);
    //    NiceInOrder2(node2);
    //     Printk(node1,2);
      //  System.out.println(Getsize(node1));
        //System.out.println(GetDepth(node1));
        //System.out.println(FindValue(node1,'u'));
        System.out.println(Is_ComTree(node1));
    int[] arr={31,23,12,66,-1,5,17,70,62,-1,-1,88,-1,55};
     Inorder_arr(arr,0,arr.length-1);
 //    inoder(node1);
        NiceInorder_arr(arr);

    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值