剑指Offer——二叉树
前言
数据结构通常是编程面试中考察的重点。在参加面试之前,应聘者需要熟练掌握链表、树、栈、队列和哈希表等数据结构,以及它们的操作。本片博文主要讲解二叉树操作的相关知识,主要包括二叉树的建立、遍历方法的循环和递归写法。
二叉树是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树的形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。
二叉树的java实现
首先创建一棵二叉树如下图,然后对这颗二叉树进行遍历操作(遍历操作的实现分为递归实现和非递归实现),同时还提供一些方法如获取双亲结点、获取左孩子、右孩子等。
-
package cn.edu.ujn.nk;
-
-
import java.util.Stack;
-
-
/**
-
* 二叉树的链式存储
-
* @author WWX
-
*/
-
public class BinaryTree {
-
-
private TreeNode root=null;
-
-
public BinaryTree(){
-
root=new TreeNode(1,"rootNode(A)");
-
}
-
-
/**
-
* 创建一棵二叉树
-
* <pre>
-
* A
-
* B C
-
* D E F
-
* </pre>
-
* @param root
-
* @author WWX
-
*/
-
public void createBinTree(TreeNode root){
-
TreeNode newNodeB = new TreeNode(2,"B");
-
TreeNode newNodeC = new TreeNode(3,"C");
-
TreeNode newNodeD = new TreeNode(4,"D");
-
TreeNode newNodeE = new TreeNode(5,"E");
-
TreeNode newNodeF = new TreeNode(6,"F");
-
root.leftChild=newNodeB;
-
root.rightChild=newNodeC;
-
root.leftChild.leftChild=newNodeD;
-
root.leftChild.rightChild=newNodeE;
-
root.rightChild.rightChild=newNodeF;
-
}
-
-
public boolean isEmpty(){
-
return root==null;
-
}
-
-
//树的高度
-
public int height(){
-
return height(root);
-
}
-
-
//节点个数
-
public int size(){
-
return size(root);
-
}
-
-
private int height(TreeNode subTree){
-
if(subTree == null)
-
return 0; // 递归结束:空树高度为0
-
else{
-
int i = height(subTree.leftChild);
-
int j = height(subTree.rightChild);
-
return (i < j) ? (j + 1) : (i + 1);
-
}
-
}
-
-
private int size(TreeNode subTree){
-
if(subTree == null){
-
return 0;
-
}else{
-
return 1 + size(subTree.leftChild) + size(subTree.rightChild);
-
}
-
}
-
-
//返回双亲结点
-
public TreeNode parent(TreeNode element){
-
return (root == null|| root == element) ? null : parent(root, element);
-
}
-
-
public TreeNode parent(TreeNode subTree,TreeNode element){
-
if(subTree == null)
-
return null;
-
if(subTree.leftChild == element || subTree.rightChild == element)
-
//返回父结点地址
-
return subTree;
-
TreeNode p;
-
// 先在左子树中找,如果左子树中没有找到,才到右子树去找
-
if((p = parent(subTree.leftChild, element)) != null)
-
//递归在左子树中搜索
-
return p;
-
else
-
//递归在右子树中搜索
-
return parent(subTree.rightChild, element);
-
}
-
-
public TreeNode getLeftChildNode(TreeNode element){
-
return (element != null) ? element.leftChild : null;
-
}
-
-
public TreeNode getRightChildNode(TreeNode element){
-
return (element != null) ? element.rightChild : null;
-
}
-
-
public TreeNode getRoot(){
-
return root;
-
}
-
-
//在释放某个结点时,该结点的左右子树都已经释放,
-
//所以应该采用后续遍历,当访问某个结点时将该结点的存储空间释放
-
public void destroy(TreeNode subTree){
-
//删除根为subTree的子树
-
if(subTree!=null){
-
//删除左子树
-
destroy(subTree.leftChild);
-
//删除右子树
-
destroy(subTree.rightChild);
-
//删除根结点
-
subTree=null;
-
}
-
}
-
-
public void traverse(TreeNode subTree){
-
System.out.println("key:"+subTree.key+"--name:"+subTree.data);;
-
traverse(subTree.leftChild);
-
traverse(subTree.rightChild);
-
}
-
-
//前序遍历
-
public void preOrder(TreeNode subTree){
-
if(subTree!=null){
-
visted(subTree);
-
preOrder(subTree.leftChild);
-
preOrder(subTree.rightChild);
-
}
-
}
-
-
//中序遍历
-
public void inOrder(TreeNode subTree){
-
if(subTree!=null){
-
inOrder(subTree.leftChild);
-
visted(subTree);
-
inOrder(subTree.rightChild);
-
}
-
}
-
-
//后续遍历
-
public void postOrder(TreeNode subTree) {
-
if (subTree != null) {
-
postOrder(subTree.leftChild);
-
postOrder(subTree.rightChild);
-
visted(subTree);
-
}
-
}
-
-
//前序遍历的非递归实现
-
public void nonRecPreOrder(TreeNode p){
-
Stack<TreeNode> stack=new Stack<TreeNode>();
-
TreeNode node=p;
-
while(node!=null||stack.size()>0){
-
while(node!=null){
-
visted(node);
-
stack.push(node);
-
node=node.leftChild;
-
}
-
while(stack.size()>0){
-
node=stack.pop();
-
node=node.rightChild;
-
}
-
}
-
}
-
-
//中序遍历的非递归实现
-
public void nonRecInOrder(TreeNode p){
-
Stack<TreeNode> stack =new Stack<BinaryTree.TreeNode>();
-
TreeNode node =p;
-
while(node!=null||stack.size()>0){
-
//存在左子树
-
while(node!=null){
-
stack.push(node);
-
node=node.leftChild;
-
}
-
//栈非空
-
if(stack.size()>0){
-
node=stack.pop();
-
visted(node);
-
node=node.rightChild;
-
}
-
}
-
}
-
-
//后序遍历的非递归实现
-
public void noRecPostOrder(TreeNode p){
-
Stack<TreeNode> stack=new Stack<BinaryTree.TreeNode>();
-
TreeNode node =p;
-
while(p!=null){
-
//左子树入栈
-
for(;p.leftChild!=null;p=p.leftChild){
-
stack.push(p);
-
}
-
//当前结点无右子树或右子树已经输出
-
while(p!=null&&(p.rightChild==null||p.rightChild==node)){
-
visted(p);
-
//纪录上一个已输出结点
-
node =p;
-
if(stack.empty())
-
return;
-
p=stack.pop();
-
}
-
//处理右子树
-
stack.push(p);
-
p=p.rightChild;
-
}
-
}
-
public void visted(TreeNode subTree){
-
subTree.isVisted=true;
-
System.out.println("key:"+subTree.key+"--name:"+subTree.data);;
-
}
-
-
-
/**
-
* 二叉树的节点数据结构
-
* @author WWX
-
*/
-
private class TreeNode{
-
private int key = 0;
-
private String data = null;
-
private boolean isVisted = false;
-
private TreeNode leftChild = null;
-
private TreeNode rightChild = null;
-
-
public TreeNode(){}
-
-
/**
-
* @param key 层序编码
-
* @param data 数据域
-
*/
-
public TreeNode(int key,String data){
-
this.key = key;
-
this.data = data;
-
this.leftChild = null;
-
this.rightChild = null;
-
}
-
}
-
-
//测试
-
public static void main(String[] args) {
-
BinaryTree bt = new BinaryTree();
-
bt.createBinTree(bt.root);
-
System.out.println("the size of the tree is " + bt.size());
-
System.out.println("the height of the tree is " + bt.height());
-
-
System.out.println("***递归实现****(前序遍历)[ABDECF]遍历*****************");
-
bt.preOrder(bt.root);
-
-
System.out.println("***递归实现****(中序遍历)[DBEACF]遍历*****************");
-
bt.inOrder(bt.root);
-
-
System.out.println("***递归实现****(后序遍历)[DEBFCA]遍历*****************");
-
bt.postOrder(bt.root);
-
-
System.out.println("***非递归实现****(前序遍历)[ABDECF]遍历*****************");
-
bt.nonRecPreOrder(bt.root);
-
-
System.out.println("***非递归实现****(中序遍历)[DBEACF]遍历*****************");
-
bt.nonRecInOrder(bt.root);
-
-
System.out.println("***非递归实现****(后序遍历)[DEBFCA]遍历*****************");
-
bt.noRecPostOrder(bt.root);
-
}
-
}
美文美图
文章来源: shq5785.blog.csdn.net,作者:No Silver Bullet,版权归原作者所有,如需转载,请联系作者。
原文链接:shq5785.blog.csdn.net/article/details/52143212