二叉树:深度遍历、广度遍历、二叉树的深度、宽度

1.实现二叉树的深度遍历(java)

(递归实现)

package cetc.tree.test;

import cetc.tree.test.BinaryTree2.TreeNode;

public class BinaryTree2 {

	/**
	 * 定义一个二叉树的节点
	 * @author Administrator
	 *
	 */
	public class TreeNode {
		int data;
		TreeNode left;
		TreeNode right;
		public TreeNode(int data, TreeNode left, TreeNode right) {
			super();
			this.data = data;
			this.left = left;
			this.right = right;
		}
		public int getData() {
			return data;
		}
		public void setData(int data) {
			this.data = data;
		}
		public TreeNode getLeft() {
			return left;
		}
		public void setLeft(TreeNode left) {
			this.left = left;
		}
		public TreeNode getRight() {
			return right;
		}
		public void setRight(TreeNode right) {
			this.right = right;
		}
	}
	
	/**\
	 * 初始化一个二叉树
	 * @return
	 */
	public TreeNode init() {
		TreeNode treeNode3 = new TreeNode(3, null, null);
		TreeNode treeNode4 = new TreeNode(4, null, null);
		TreeNode treeNode6 = new TreeNode(6, null, null);
		TreeNode treeNode2 = new TreeNode(2, treeNode3, treeNode4);
		TreeNode treeNode5 = new TreeNode(5, null, treeNode6);
		TreeNode treeNodeRoot = new TreeNode(1, treeNode2, treeNode5);
		return treeNodeRoot;
	}
	
	public void printData(TreeNode treeNode) {
		System.out.println("current node data: "+treeNode.getData());
	}
	
	/*
	 * 先序遍历:先跟节点,然后左右节点
	 */
	public void DLR(TreeNode treeNode) {
		printData(treeNode);
		if (treeNode.getLeft() != null) {
			DLR(treeNode.getLeft());
		}
		if (treeNode.getRight()!= null) {
			DLR(treeNode.getRight());
		}
	}
	/*
	 * 中序遍历/中根遍历:先跟节点,然后左右节点
	 */
	public void LDR(TreeNode treeNode) {
		if (treeNode.getLeft() != null) {
			LDR(treeNode.getLeft());
		}
		printData(treeNode);
		if (treeNode.getRight()!= null) {
			LDR(treeNode.getRight());
		}
	}
	/*
	 * 后序遍历:先跟节点,然后左右节点
	 */
	public void LRD(TreeNode treeNode) {
		if (treeNode.getLeft() != null) {
			LRD(treeNode.getLeft());
		}
		if (treeNode.getRight()!= null) {
			LRD(treeNode.getRight());
		}
		printData(treeNode);
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        BinaryTree2 binaryTree=new BinaryTree2();
        TreeNode node=binaryTree.init();
        System.out.println("DLR:");
        binaryTree.DLR(node);
        System.out.println("LDR");
        binaryTree.LDR(node);
        System.out.println("LRD");
        binaryTree.LRD(node);

	}
}

2.求二叉树的深度、广度(java)

(1)求二叉树的深度

//节点数据结构
class TreeNode {
    TreeNode left = null;
    TreeNode right = null;
}
 

//最大深度,基本思路是:使用递归,分别求出左子树的深度、右子树的深度,两个深度的较大值+1就是最大深度。

// 获取最大深度
    public static int getMaxDepth(TreeNode treeNode) {
        if (treeNode == null)
            return 0;
        else {
            int left = getMaxDepth(treeNode.left);
            int right = getMaxDepth(treeNode.right);
            return 1 + Math.max(left, right);
        }
    }
    // 获取最小深度
    public static int getMinDepth(TreeNode treeNode) {
        if (treeNode == null)
            return 0;
        else {
            int left = getMinDepth(treeNode.left);
            int right = getMinDepth(treeNode.right);
            return 1 + Math.min(left, right);
        }
    }

(2)最大宽度,基本思路:使用队列,按层次遍历二叉树。在上一层遍历完成后,下一层的所有节点已经放到队列中,此时队列中的元素个数就是下一层的宽度。以此类推,依次遍历下一层即可求出二叉树的最大宽度。

// 获取最大宽度
    public static int getMaxWidth(TreeNode treeNode) {
        if (treeNode == null)
            return 0;

        Queue<TreeNode> queue = new ArrayDeque<TreeNode>();
        int maxWitdth = 1; // 最大宽度
        queue.add(treeNode); // 入队

        while (true) {
            int len = queue.size(); // 当前层的节点个数
            if (len == 0)
                break;
            while (len > 0) {// 如果当前层,还有节点
                TreeNode node = queue.poll();
                len--;
                if (node.left != null)
                    queue.add(node.left); // 下一层节点入队
                if (node.right != null)
                    queue.add(node.right);// 下一层节点入队
            }
            maxWitdth = Math.max(maxWitdth, queue.size());
        }
        return maxWitdth;
    }

3.广度优先遍历二叉树

广度优先周游二叉树(层序遍历)是用队列来实现的,从二叉树的第一层(根结点)开始,自上至下逐层遍历;在同一层中,按照从左到右的顺序对结点逐一访问。

按照从根结点至叶结点、从左子树至右子树的次序访问二叉树的结点。算法:

1初始化一个队列,并把根结点入列队;

2当队列为非空时,循环执行步骤3到步骤5,否则执行6;

3出队列取得一个结点,访问该结点;

4若该结点的左子树为非空,则将该结点的左子树入队列;

5若该结点的右子树为非空,则将该结点的右子树入队列;

6结束。

4.非递归深度优先遍历二叉树

栈是实现递归的最常用的结构,利用一个栈来记下尚待遍历的结点或子树,以备以后访问,可以将递归的深度优先遍历改为非递归的算法。

  1. 非递归前序遍历:遇到一个结点,就访问该结点,并把此结点推入栈中,然后下降去遍历它的左子树。遍历完它的左子树后,从栈顶托出这个结点,并按照它的右链接指示的地址再去遍历该结点的右子树结构。

  2. 非递归中序遍历:遇到一个结点,就把它推入栈中,并去遍历它的左子树。遍历完左子树后,从栈顶托出这个结点并访问之,然后按照它的右链接指示的地址再去遍历该结点的右子树。

  3. 非递归后序遍历:遇到一个结点,把它推入栈中,遍历它的左子树。遍历结束后,还不能马上访问处于栈顶的该结点,而是要再按照它的右链接结构指示的地址去遍历该结点的右子树。遍历遍右子树后才能从栈顶托出该结点并访问之。另外,需要给栈中的每个元素加上一个特征位,以便当从栈顶托出一个结点时区别是从栈顶元素左边回来的(则要继续遍历右子树),还是从右边回来的(该结点的左、右子树均已周游)。特征为Left表示已进入该结点的左子树,将从左边回来;特征为Right表示已进入该结点的右子树,将从右边回来。

  4. 简洁的非递归前序遍历:遇到一个结点,就访问该结点,并把此结点的非空右结点推入栈中,然后下降去遍历它的左子树。遍历完左子树后,从栈顶托出一个结点,并按照它的右链接指示的地址再去遍历该结点的右子树结构。

猜你喜欢

转载自blog.csdn.net/fct2001140269/article/details/83043515