二叉树递归和非递归遍历以及层次构建节点数为n的二叉树

本文详细探讨了二叉树的递归和非递归遍历方法,包括前序、中序、后序遍历,并展示了递归与非递归的实现方式。此外,还介绍了如何通过卡特兰数构建节点数为n的所有二叉树,包括层次遍历和层次创建的方法。代码示例和测试用例辅助理解各个遍历过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录:

  1. 二叉树深度
  2. 二叉树前序遍历
    1. 递归实现
    2. 二种非递归实现
  3. 二叉树中序遍历:
    1. 递归实现
    2. 非递归实现
  4. 二叉树后序遍历:
    1. 递归实现
    2. 非递归实现
  5. 二叉树层次遍历
  6. 二叉树层次创建,创建方法遵循卡特兰数



import java.util.Queue;

import java.util.Stack;

 

/*

 * ssuchange

 */

public class BinTreeTraversal {

    public static final int SIZE = 30;

    public static final char NULLNODE = '#';

    public static char[] Sequeuce =newchar[100];

    public static int SeqCount;

 

    static class Node {

        public Node(char ch) {

            val = ch;

            left = null;

            right = null;

        }

 

        char val;

        Node left;

        Node right;

    }

 

    public static void main(String[] args) {

        System.out.println("Start");

        // testTree();

        for (int i = 0; i < 26; i++)

            catalanCreateBinTree(i);

        System.out.println("End");

    }

 

    //         a

    //      /    \

    //     b      c

    //    / \    / \

    //   d  e   f   g

    //  /   /\     / \

    // h   i  j   k   l


    public static void testTree() {

        Node a = new Node('a');

        Node b = new Node('b');

        Node c = new Node('c');

        Node d = new Node('d');

        Node e = new Node('e');

        Node f = new Node('f');

        Node g = new Node('g');

        Node h = new Node('h');

        Node i = new Node('i');

        Node j = new Node('j');

        Node k = new Node('k');

        Node l = new Node('l');

        a.left = b;

        a.right = c;

        b.left = d;

        b.right = e;

        c.left = f;

        c.right = g;

        d.left = h;

        e.left = i;

        e.right = j;

        g.left = k;

        g.right = l;

        try {

            testTree(a);

        } catch (Exception e1) {

            e1.printStackTrace();

        }

    }

 

    public static void testTree(Node tree)throws Exception {

        String rightStr, computeStr;

        Println("****************");

        Println("Depth:\t" +depthRec(tree));

        Println("递归前序遍历");

        SeqCount = 0;

        preTraRec(tree);

        rightStr = getSequence();

        Println();

        Println("非递归前序遍历");

        Println("方法一");

        SeqCount = 0;

        preTraNoRec1(tree);

        computeStr = getSequence();

        if (!computeStr.equals(rightStr))

            throw new Exception("RightStr isnot equal computeStr!");

        Println();

        Println("方法二");

        SeqCount = 0;

        preTraNoRec2(tree);

        computeStr = getSequence();

        if (!computeStr.equals(rightStr))

            throw new Exception("RightStr isnot equal computeStr!");

        Println();

        Println("递归中序遍历");

        SeqCount = 0;

        midTraRec(tree);

        rightStr = getSequence();

        Println();

        Println("非递归中序遍历");

        SeqCount = 0;

        midTraNoRec(tree);

        computeStr = getSequence();

        if (!computeStr.equals(rightStr))

            throw new Exception("RightStr isnot equal computeStr!");

        Println();

        Println("递归后序遍历");

        SeqCount = 0;

        postTraRec(tree);

        rightStr = getSequence();

        Println();

        Println("非递归后序遍历");

        SeqCount = 0;

        postTraNoRec(tree);

        computeStr = getSequence();

        if (!computeStr.equals(rightStr))

            throw new Exception("RightStr isnot equal computeStr!");

        Println();

        Println("****************");

    }

 

    // 求二叉树深度

    public static int depthRec(Node tree) {

        if (tree ==null)

            return 0;

        // 递归求解左右子树深度。

        int leftDepth =depthRec(tree.left);

        int rightDepth =depthRec(tree.right);

        // 取左右子树中大的加1作为当前深度。

        return (leftDepth > rightDepth ? leftDepth: rightDepth) + 1;

    }

 

    // 访问节点

    public static void visit(Node node) {

        if (node ==null)

            return;

        Print(node.val +" ");

        Sequeuce[SeqCount++] = node.val;

    }

 

    public static String getSequence() {

        return new String(Sequeuce, 0,SeqCount);

    }

 

    // 前序遍历递归求解

    public static void preTraRec(Node tree) {

        if (tree ==null)

            return;

        visit(tree);

        preTraRec(tree.left);

        preTraRec(tree.right);

    }

 

    // 前序遍历非递归求解

    // 先访问当前节点,在不断向下压栈找左子树,最后出栈访问右子树,此时,右子树又成为一颗单独子树

    public static void preTraNoRec1(Node tree) {

        if (tree ==null)

            return;

        Node node = tree;

        Node[] stack = new Node[SIZE];

        int top = 0;

        while (node !=null || top > 0) {

            while (node !=null) {

                // 访问当前节点

                visit(node);

                // 记录当前节点,用于查找当前节点的右子树

                stack[top++] = node;

                // 访问当前节点的左子树

                node = node.left;

            }

            if (top > 0) {

                // 访问完当前左子树,出栈访问右子树

                node = stack[--top].right;

            }

        }

    }

 

    public static void preTraNoRec2(Node tree) {

        if (tree ==null)

            return;

        Node node = tree;

        Node[] stack = new Node[SIZE];

        int top = 0;

        stack[top++] = node;

        while (top > 0) {

            // 根节点出栈

            node = stack[--top];

            // 访问根节点

            visit(node);

            // 因为下一次出栈先访问左子树,所以先压栈右子树,再压栈左子树,使得左子树先出栈

            // 右子树节点压栈

            if (node.right !=null)

                stack[top++] = node.right;

            // 左子树节点压栈

            if (node.left !=null)

                stack[top++] = node.left;

            // 根节点访问完成后,将左右子树压栈,然后根节点丢弃。

        }

    }

 

    // 中序遍历递归求解

    public static void midTraRec(Node tree) {

        if (tree ==null)

            return;

        midTraRec(tree.left);

        visit(tree);

        midTraRec(tree.right);

    }

 

    // 中序遍历非递归求解

    // 与前序遍历非递归求解相同,只要改变访问节点的位置。

    public static void midTraNoRec(Node tree) {

        if (tree ==null)

            return;

        Node node = tree;

        Node[] stack = new Node[SIZE];

        int top = 0;

        while (node !=null || top > 0) {

            while (node !=null) {

                // 记录当前节点,用于查找当前节点的右子树

                stack[top++] = node;

                // 访问当前节点的左子树

                node = node.left;

            }

            if (top > 0) {

                // 访问完当前左子树,出栈访问根节点

                node = stack[--top];

                // 访问根节点

                visit(node);

                // 访问右子树

                node = node.right;

            }

        }

    }

 

    // 后序遍历递归求解

    public static void postTraRec(Node tree) {

        if (tree ==null)

            return;

        postTraRec(tree.left);

        postTraRec(tree.right);

        visit(tree);

    }

 

    // 后序遍历非递归求解

    public static void postTraNoRec(Node tree) {

        if (tree ==null)

            return;

        Node node = tree;

        Node[] stackCom = new Node[SIZE];

        int topCom = 0;

        Node[] stackVis = new Node[SIZE];

        int topVis = 0;

        stackCom[topCom++] = node;

        while (topCom > 0) {

            node = stackCom[--topCom];

            stackVis[topVis++] = node;

            if (node.left !=null)

                stackCom[topCom++] = node.left;

            if (node.right !=null)

                stackCom[topCom++] = node.right;

        }

        while (topVis > 0) {

            visit(stackVis[--topVis]);

        }

    }

 

    static class Queue<T> {

        Object[] queue = new Object[SIZE];

        int front = 0;

        int rear = 0;

 

        public void enqueue(T t) {

            if ((rear + 1) %SIZE ==front) {

                try {

                    thrownew Exception("Queue isfull!");

                } catch (Exception e) {

                    e.printStackTrace();

                }

            }

            queue[rear] = t;

            rear = (rear + 1) %SIZE;

        }

 

        public T dequeue() {

            if (rear ==front) {

                try {

                    thrownew Exception("Queue isempty!");

                } catch (Exception e) {

                    e.printStackTrace();

                }

            }

            T t = (T) queue[front];

            front = (front + 1) %SIZE;

            return t;

        }

 

        public boolean isEmpty() {

            returnrear ==front;

        }

    }

 

    // 层次遍历

    public static void levelTra(Node tree) {

        if (tree ==null)

            return;

        Queue<Node> queue = newQueue<Node>();

        queue.enqueue(tree);

        while (!queue.isEmpty()) {

            Node node = queue.dequeue();

            visit(node);

            if (node.left !=null)

                queue.enqueue(node.left);

            if (node.right !=null)

                queue.enqueue(node.right);

        }

    }

 

    // 层次构建二叉树

    public static Node levelCreate(char[] array) {

        if (array ==null || array.length == 0)

            return null;

        int index = 0;

        Node tree = null;

        if (array[index] ==NULLNODE)

            return tree;

        Queue<Node> queue = newQueue<Node>();

        tree = new Node(array[index]);

        index++;

        queue.enqueue(tree);

        while (!queue.isEmpty() && index <array.length) {

            Node node = queue.dequeue();

            if (array[index] ==NULLNODE)

                node.left = null;

            else {

                node.left = new Node(array[index]);

                queue.enqueue(node.left);

            }

            index++;

            if (array[index] ==NULLNODE)

                node.right = null;

            else {

                node.right = new Node(array[index]);

                queue.enqueue(node.right);

            }

            index++;

        }

        if (queue.isEmpty() && index == array.length)

            return tree;

        return null;

    }

 

    public static void testBinTree(char[] array) {

        // for (int i = 0; i < array.length; i++) {

        // Print(array[i]);

        // }

        // Println();

        Node tree = levelCreate(array);

        try {

            testTree(tree);

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

 

    // 卡特兰数构建二叉树层次遍历序列

    // 令二叉树节点总数为N,有另个孩子的节点数为a,一个孩子的节点数为b,没有孩子的节点为c

    // 2a+b+1=n,即除了根节点的所有节点都是其父节点的孩子节点,孩子节点加上根节点构成整个二叉树;

    // a+b+c=n,即二叉树节点由非叶子节点(双孩子节点、单孩子节点)和叶子节点组成。

    // b+2c=n+1,即非空节点数为n的二叉树有n+1个空节点。

    // 非空节点数为n的二叉树满足卡特兰数的构建原则,推导见卡特兰数百度百科。

    // 非空节点数为n的二叉树的层次遍历序列共有2*n+1个数,最后一个一定为空节点,前2*n个节点构建原则为:

    // n1n0构成长度为2*n的序列,任意位置前面和当前位置的1的个数一定大于等于0的个数,1代表非空节点,0代表空节点


//http://www.cppblog.com/MiYu/archive/2010/08/07/122573.html

    public static void catalanCreateBinTree(int n) {

        if (n <= 0 || n > 25)

            return;

        boolean[] arr =newboolean[2 * n];

        catalan(arr, 0, n);

    }


    // Catalan序列递归构造方法:

    // 如果当前位置前面的1的个数大于前面0的个数,当前位置可以填充1

    // 如果当前位置前面的1的个数小于n,当前位置可以填充1

    // 递归结束条件为当前位置前面的1的个数等于n,则当前位置到序列结尾都填充0,构造结束。

    public static void catalan(boolean[] arr,int index,int trueLeft) {

        if (trueLeft == 0) {

            char[] array =newchar[arr.length + 1];

            char ch ='a';

            for (int i = 0; i < index; i++) {

                if (arr[i])

                    array[i] = ch++;

                else

                    array[i] = NULLNODE;

            }

            for(int i=index;i<array.length;i++)

                array[i] = NULLNODE;

            testBinTree(array);

        } else {

            arr[index] = true;

            catalan(arr, index + 1,trueLeft - 1);

            if (index + 1 <= arr.length - 2 * trueLeft) {

                arr[index] = false;

                catalan(arr, index + 1,trueLeft);

            }

        }

    }


    public static void Print(String str) {

        System.out.print(str);

    }

 

    public static void Println() {

        System.out.println();

    }

 

    public static void Println(String str) {

        Print(str);

        Println();

    }

}

 

参考链接:

http://blog.youkuaiyun.com/kofsky/article/details/2886453

下载地址:

http://download.youkuaiyun.com/detail/ssuchange/6730285

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值