二叉树遍历

二叉树的建立

上图是按层遍历的结果:

根节点是b,它的左孩子是c,右孩子是d

c节点的左孩子是e,右孩子是f

d节点的左孩子是a

规律:

https://blog.csdn.net/u010842515/article/details/68951783

  1. 父节点数组下标从0到 n/2 -1 ,但是遍历时要小于n/2-1,因为最后一个父节点可能没有右孩子,当n/2-1为奇数时才有右孩子,为偶数时只有左孩子。

  2. 结点左孩子下标为2n+1,右孩子下标为2n+2

`

class BinaryTreeNode{
char value;
BinaryTreeNode leftNode;
BinaryTreeNode rightNode;

public BinaryTreeNode(){

}

public BinaryTreeNode(char value){
    this.value=value;
}

// 创建二叉树
//递归
public BinaryTreeNode createBinaryTree(BinaryTreeNode node,char[] data,int i){
    //如果data数组里面没有元素或i大于data数组长度
    if(data.length==0||i>data.length || data[i] == ' '){
        return null;
    }

    if(i<data.length){
        if(node==null){
            node=new BinaryTreeNode();
        }
        node.value=data[i];
        node.leftNode=createBinaryTree(node.leftNode,data,2*i+1);
        node.rightNode=createBinaryTree(node.rightNode,data,2*i+2);
    }
    return  node;
}
//创建二叉树
//非递归
public BinaryTreeNode createBinaryTree(char[] data){
    if(data.length==0){
        return null;
    }
    List<BinaryTreeNode> list=new ArrayList<>();
    for(int i=0;i<data.length;i++){
        if (data[i] == ' ') {
            list.add(null);
        } else {
            list.add(new BinaryTreeNode(data[i]));
        }
    }

    for(int i=0;i<data.length/2-1;i++){
        if (list.get(i) == null) {
            continue;
        } else {
            //左孩子
            list.get(i).leftNode = list.get(i * 2 + 1);
            //右孩子
            list.get(i).rightNode = list.get(i * 2 + 2);
        }
    }
    //最后一个父节点:因为最后一个父节点可能没有右孩子,所以单独拿出来处理
    int last=data.length/2-1;

    list.get(last).leftNode=list.get(last*2+1);
    //长度为奇数说明有右孩子
    if(data.length%2==1){
        list.get(last).rightNode=list.get(last*2+2);
    }
    //返回根节点
    return list.get(0);

}
}

`

递归遍历

前序

`

 //前序遍历
//递归
public static void preOrder(BinaryTreeNode node){
    if(node==null){
        return;
    }
    System.out.print(node.value+" ");
    preOrder(node.leftNode);
    preOrder(node.rightNode);

}

`

中序

`

//中序遍历
//递归
public static void inOrder(BinaryTreeNode node){
    if(node==null){
        return;
    }
    preOrder(node.leftNode);
    System.out.print(node.value+" ");
    preOrder(node.rightNode);

}

`

后序

`

//后序遍历
//递归
public static void postOrder(BinaryTreeNode node){
    if(node==null){
        return;
    }
    preOrder(node.leftNode);
    preOrder(node.rightNode);
    System.out.print(node.value+" ");

}

`

结果:

按层遍历

需要用到队列

`

//按层遍历
public static void topToBottom(BinaryTreeNode node){
    Queue<BinaryTreeNode> queue=new LinkedList<>();
    if (node==null){
        return;
    }
    queue.add(node);
    while(!queue.isEmpty()){
        BinaryTreeNode tempNode=queue.poll();
        if(tempNode.leftNode!=null)
            queue.add(tempNode.leftNode);
        if(tempNode.rightNode!=null)
            queue.add(tempNode.rightNode);
        System.out.print(tempNode.value+" ");
    }
}

`

非递归遍历

先序

`

//前序遍历
//非递归
public static void preOrderTraverseTree(BinaryTreeNode node){
    BinaryTreeNode temp=node;
    Stack<BinaryTreeNode> stack=new Stack<>();
    if(temp==null){
        System.out.println("空");
    }
    while(temp!=null || !stack.empty()){
        if(temp!=null){
            stack.push(temp);
            System.out.print(temp.value+" ");
            temp=temp.leftNode;
        }else{
            temp=stack.pop();
            temp=temp.rightNode;
        }
    }
}

`

中序

`

//中序序遍历
//非递归
public static void inOrderTraverseTree(BinaryTreeNode node){
    BinaryTreeNode temp=node;
    Stack<BinaryTreeNode> stack=new Stack<>();
    if(temp==null){
        System.out.println("空");
    }
    while(temp!=null || !stack.empty()){
        if(temp!=null){
            stack.push(temp);
            temp=temp.leftNode;
        }else{
            temp=stack.pop();
            System.out.print(temp.value+" ");
            temp=temp.rightNode;
        }
    }
}

`

后序

https://www.cnblogs.com/fengxmx/p/3764512.html

要保证根节点要在左孩子和右孩子都访问下才能访问,对于任意节点x,先入栈,若其没有左孩子和右孩子则可以直接访问。若存在左孩子或右孩子需要左右孩子都访问后才能访问。若非上述两种情况,则将x的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。

`

//后序遍历
//非递归
public static void postOrderTraverseTree(BinaryTreeNode node){
    BinaryTreeNode temp=node;
    Stack<BinaryTreeNode> stack=new Stack<>();
    if(temp==null){
        System.out.println("空");
    }
    stack.push(node);
    BinaryTreeNode pre=null,cur=null;
    while(!stack.empty()){
        cur=stack.peek();
        if((cur.leftNode==null&&cur.rightNode==null)||(pre!=null&&pre==cur.leftNode||pre==cur.rightNode)){
            System.out.print(cur.value+" ");
            pre=cur;
            stack.pop();
        }else{
            if(cur.rightNode!=null){
                stack.push(cur.rightNode);
            }
            if(cur.leftNode!=null){
                stack.push(cur.leftNode);
            }
        }
    }
}

`

posted @ 2018-06-05 11:37  罗贱人  阅读(147)  评论(0编辑  收藏  举报