二叉树的创建和遍历

最近找实习,觉得需要记录一下自己学习的内容。第一次写博客,但愿有个好的开始。

前天去华为面试,面了50分钟,最后败倒在一棵树下(当时遍历反了,从root往子节点遍历,其实是从子节点向上遍历),好傻,都怪自己平时写代码比较少,代码这种东西,还是得多练。

二叉树:如果只有一个节点,那么这个节点就是根节点;如果不只一个节点,那么它的左子树和右子树都是一棵二叉树。这是二叉树的递归定义。

二叉树的建立,从根开始,先来看看普通的二叉树的建立(非排序),用for循环即可。如下(这个方法参考自http://ocaicai.iteye.com/blog/1047397,此博主写的很详细)。

<span style="white-space:pre">	</span>/**
	 * for循环遍历建树,此方法建的不是排序树
	 * @param array
	 * @return
	 */
	public Node creatBinaryTreeFor(int[] array){
		List<Node> nodeList = new LinkedList<Node>();
		//将数组中的数字转换为node.
		for (int i = 0; i < array.length; i++) {
			nodeList.add(new Node(array[i]));
		}
		
		for (int parentIndex = 0; parentIndex < nodeList.size()/2 - 1; parentIndex++) {
			nodeList.get(parentIndex).leftChild = nodeList.get(parentIndex*2 +1);
			nodeList.get(parentIndex).rightChild = nodeList.get(parentIndex*2 +2);
		}
		int lastParentNode = nodeList.size()/2 -1;
		nodeList.get(lastParentNode).leftChild = nodeList.get(lastParentNode*2 + 1);
		
		if (nodeList.size()%2 == 1) {
			nodeList.get(lastParentNode).rightChild = nodeList.get(lastParentNode*2 + 2);
		}
		return nodeList.get(0);
	}
然后看看二叉排序树的建立,虽然采用递归,但是一次只能建一个节点,可以在main函数里循环调用这个递归函数。

递归方法如下(此方法参考自http://blog.csdn.net/yhhazr/article/details/7944089,哎呀,现在这种方法基本都定型了,我仅引用我参考的这个,至于这个方法原创是谁,不去追究)。

<span style="white-space:pre">	</span>/**
	 * 递归构建二叉排序树
	 * @param node
	 * @param data
	 */
	public void creatBinaryTree(Node node, int data){
		if (node == null) {
			node = new Node(data);
		}else {
			if (data < node.data) {
				if (node.leftChild == null) {
					node.leftChild = new Node(data);
				}else {
					creatBinaryTree(node.leftChild, data);
				}
			}else {
				if (node.rightChild == null) {
					node.rightChild = new Node(data);
				}else {
					creatBinaryTree(node.rightChild, data);
				}
			}
		}
	}
然后看看遍历,包括前序遍历,中序遍历和后序遍历。

中序遍历:先遍历左子树,再访问根节点,最后遍历右节点。看代码:

<span style="white-space:pre">	</span>/**
	 * 中序遍历
	 * @param node
	 */
	public List  inOrderTranverse(Node node){
		List<Integer> list = new ArrayList<Integer>();
		if (node != null) {
			list.addAll(inOrderTranverse(node.leftChild));
			list.add(node.data);
			list.addAll(inOrderTranverse(node.rightChild));
		}
		return list;
	}
上面这个方法返回的是中序遍历的序列,如果是二叉排序树,那么这个序列刚好是有序的,也就是利用二叉树实现排序的就是它了。

再看前序和后序遍历:

<span style="white-space:pre">	</span>/**
	 * 前序遍历
	 * @param node
	 */
	public void preOderTranverse(Node node){
		if (node != null) {
			System.out.println(node.data);
			preOderTranverse(node.leftChild);
			preOderTranverse(node.rightChild);
		}
	}
	
	/**
	 * 后序遍历
	 * @param node
	 */
	public void postOrderTranverse(Node node){
		if (node != null) {
			postOrderTranverse(node.leftChild);
			postOrderTranverse(node.rightChild);
			System.out.println(node.data);
		}
	}
前序和后序没有返回值,但是在遍历的时候把遍历的值打印了出来。

然后是main方法:

public static void main(String[] args) {
		int[] a = {1,2,3,4,5,6,3,7,8,9,12,0,10};
		BinaryTree bt = new BinaryTree();
//		Node root = bt.creatBinaryTreeFor(a);
//		bt.preOderTranverse(root);
//		bt.inOrderTranverse(root);
		Node root = bt.new Node(a[0]);
		for (int i = 1; i < a.length; i++) {
			bt.creatBinaryTree(root, a[i]);
		}
		List list = bt.inOrderTranverse(root);
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
	}


最后附上所有代码:

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class BinaryTree {
	
	/**
	 * 内部类,表示树的一个节点的数据结构
	 * 左孩子,右孩子,data.
	 * @author mzdong
	 *
	 */
	private class Node{
		private Node leftChild;
		private Node rightChild;
		private int data;
		
		public Node(int data){
			this.leftChild = null;
			this.rightChild = null;
			this.data = data;
		}
	}
	
	/**
	 * for循环遍历建树,此方法建的不是排序树
	 * @param array
	 * @return
	 */
	public Node creatBinaryTreeFor(int[] array){
		List<Node> nodeList = new LinkedList<Node>();
		//将数组中的数字转换为node.
		for (int i = 0; i < array.length; i++) {
			nodeList.add(new Node(array[i]));
		}
		
		for (int parentIndex = 0; parentIndex < nodeList.size()/2 - 1; parentIndex++) {
			nodeList.get(parentIndex).leftChild = nodeList.get(parentIndex*2 +1);
			nodeList.get(parentIndex).rightChild = nodeList.get(parentIndex*2 +2);
		}
		int lastParentNode = nodeList.size()/2 -1;
		nodeList.get(lastParentNode).leftChild = nodeList.get(lastParentNode*2 + 1);
		
		if (nodeList.size()%2 == 1) {
			nodeList.get(lastParentNode).rightChild = nodeList.get(lastParentNode*2 + 2);
		}
		return nodeList.get(0);
	}
	
	/**
	 * 递归构建二叉排序树
	 * @param node
	 * @param data
	 */
	public void creatBinaryTree(Node node, int data){
		if (node == null) {
			node = new Node(data);
		}else {
			if (data < node.data) {
				if (node.leftChild == null) {
					node.leftChild = new Node(data);
				}else {
					creatBinaryTree(node.leftChild, data);
				}
			}else {
				if (node.rightChild == null) {
					node.rightChild = new Node(data);
				}else {
					creatBinaryTree(node.rightChild, data);
				}
			}
		}
	}
	
	/**
	 * 前序遍历
	 * @param node
	 */
	public void preOderTranverse(Node node){
		if (node != null) {
//			System.out.println(node.data);
			preOderTranverse(node.leftChild);
			preOderTranverse(node.rightChild);
		}
	}
	
	/**
	 * 后序遍历
	 * @param node
	 */
	public void postOrderTranverse(Node node){
		if (node != null) {
			postOrderTranverse(node.leftChild);
			postOrderTranverse(node.rightChild);
			System.out.println(node.data);
		}
	}
	
	/**
	 * 中序遍历
	 * @param node
	 */
	public List  inOrderTranverse(Node node){
		List<Integer> list = new ArrayList<Integer>();
		if (node != null) {
			list.addAll(inOrderTranverse(node.leftChild));
			list.add(node.data);
			list.addAll(inOrderTranverse(node.rightChild));
		}
		return list;
	}
	
	public static void main(String[] args) {
		int[] a = {1,2,3,4,5,6,3,7,8,9,12,0,10};
		BinaryTree bt = new BinaryTree();
//		Node root = bt.creatBinaryTreeFor(a);
//		bt.preOderTranverse(root);
//		bt.inOrderTranverse(root);
		Node root = bt.new Node(a[0]);
		for (int i = 1; i < a.length; i++) {
			bt.creatBinaryTree(root, a[i]);
		}
		List list = bt.inOrderTranverse(root);
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值