给你一颗二叉树,然后让你用代码实现创建的过程,紧接着用代码实现它的前序,中序,后序遍历。
例如给妮这样一颗二叉树
代码如下(注释很清楚)
package jzoffer;
/*
*二叉树链式存储
*@author LSM
*/
public class Tree {
private TreeNoder root = null; //先定义一个根节点
public Tree() {
root = new TreeNoder(1, "rootNode(A)"); //在初始化的时候吧根节点初始化为A key当然赋值为1
}
/**
* 创建一棵二叉树
* <pre>
* A
* B C
* D E F
* </pre>
* @param root
* @author LSM
*/
public void createTree(TreeNoder treeNoder){ //参数主要就是为了给根节点加节点
TreeNoder treeNoderB = new TreeNoder(2, "B"); //看上面的图
TreeNoder treeNoderC = new TreeNoder(3, "C");
TreeNoder treeNoderD = new TreeNoder(4, "D");
TreeNoder treeNoderE = new TreeNoder(5, "E");
TreeNoder treeNoderF = new TreeNoder(6, "F");
treeNoder.leftChild = treeNoderB;
treeNoder.rightChild = treeNoderC;
treeNoder.leftChild.leftChild = treeNoderD;
treeNoder.rightChild.rightChild = treeNoderF;
treeNoder.leftChild.rightChild = treeNoderE; //这样真的好麻烦这就算完成了
}
public boolean isEmpty() { //这个就是判断根节点是否为null
return root==null;
}
public int height(){ //主要为了后边调用方便 再不用写root了
return height(root);
}
public int height(TreeNoder treeNoderHeight){ //这里也是递归的方法
if(treeNoderHeight == null){
return 0; //空树的高度为0
}else{
int i = height(treeNoderHeight.leftChild);
int j = height(treeNoderHeight.rightChild);
return (i<j)?(j+1):(i+1); //仔细揣摩下这句话的意思
}
}
//主要为了后边调用方便 再不用写root了
public int size(){
return size(root);
}
public int size(TreeNoder treeNoderSize){
if(treeNoderSize == null){
return 0;
}else{
return 1+size(treeNoderSize.leftChild)+size(treeNoderSize.rightChild); //叶子节点都是0 再加上自身 自己揣摩
}
}
public TreeNoder parent(TreeNoder treeNoderParent){
if(treeNoderParent == null){
return null;
}
//这个方法和下面的方法是连着的,只不过为了更方便吧
//其实完全可以只用写下面一个方法,但是如果只写下面一个方法时候
//你每次的参数就必须写一个root 这就很烦了
return (root == null || root == treeNoderParent)?null:parent(root, treeNoderParent);
}
public TreeNoder parent(TreeNoder treeNoderParent,TreeNoder treeNoderSize){
if(treeNoderParent == null){ //上面也有可能有一种情况就是 根节点root本身就为空那 那我们肯定就自己返回了
return null;
}
if(treeNoderParent.leftChild == treeNoderSize ||treeNoderParent.rightChild == treeNoderSize){
return treeNoderSize;//如果的根节点的左边的孩子和右边的孩子的话,那么这个节点的双亲节点肯定就是根节点。
}
TreeNoder treeNoderP;
//递归在左子树中查找
if((treeNoderP = parent(treeNoderParent.leftChild, treeNoderSize))!= null){ //判断左子树
return treeNoderP;
}else{
//递归在右子树中查找
return parent(treeNoderParent.rightChild, treeNoderSize);
}
}
//得到一个节点的左孩子节点
public TreeNoder getLeftChildNode(TreeNoder leftChildNode){
return (leftChildNode!=null)?leftChildNode.leftChild:null;
}
//得到一个节点的右孩子节点
public TreeNoder getRightChildNode(TreeNoder RightChildNode){
return (RightChildNode!=null)?RightChildNode.rightChild:null;
}
public TreeNoder getRoot(){
return root;
}
//在释放某个节点的时候,该节点的左右子树都已经释放
//所以应该采用后续遍历,当访问某个节点时候,将该节点存储的控件释放
public void destroy(TreeNoder treeNoderElement){
if(treeNoderElement != null){
//删除左子树
destroy(treeNoderElement.leftChild);
//删除右子树
destroy(treeNoderElement.rightChild);
//最后要将这个节点也就是 相对根节点置null 也就是删除
treeNoderElement = null;
}
}
//这个是输出这棵树
public void traverse(TreeNoder treeNoder){
//先带有一个标志
System.out.println("KEY" + treeNoder.key + "--name:" + treeNoder.data);
//然后就是老套路递归左子树
traverse(treeNoder.leftChild);
//紧接着右子树
traverse(treeNoder.rightChild);
}
//前序遍历--------
public void preOrder(TreeNoder treeNoder){
//前序遍历第一下肯定是输出根节点的嘛
if(treeNoder != null){
//这个方法就是输出一下根节点,至于为什么要写一个方法 还是为了方便调用呗
//以后左子树也要调用这个方法,右边的也是
visted(treeNoder);
//按照前序遍历的规则肯定就是先根再左边再右边
preOrder(treeNoder.leftChild);
preOrder(treeNoder.rightChild);
}
}
//接下来中序遍历 就是按照 "左根右"的方式
public void inOrder(TreeNoder treeNoder){
if(treeNoder != null){
inOrder(treeNoder.leftChild);
visted(treeNoder);
inOrder(treeNoder.rightChild);
}
}
//接下来后序遍历 就是按照 "左右根"的方式
public void postOrder(TreeNoder treeNoder){
if(treeNoder != null){
postOrder(treeNoder.leftChild);
postOrder(treeNoder.rightChild);
visted(treeNoder);
}
}
public void visted(TreeNoder treeNoder){
treeNoder.isVisted = true;
System.out.println("KEY" + treeNoder.key + "--name:" + treeNoder.data);
}
public static void main(String[] args) {
Tree t = new Tree();
t.createTree(t.root);
System.out.println("这棵树的size为" + t.size());
System.out.println("这棵树的高为" + t.height());
System.out.println("*******(前序遍历)-LSM-[ABDECF]遍历*****************");
t.preOrder(t.root);
System.out.println("*******(中序遍历)-LSM-[DBEACF]遍历*****************");
t.inOrder(t.root);
System.out.println("*******(后序遍历)-LSM-[DEBFCA]遍历*****************");
t.postOrder(t.root);
}
}
/*
* 二叉树节点的数据结构
* @author LSM
*/
class TreeNoder{
int key = 0; //这个主要是为了记录他遍历的顺序
String data = null; //这个主要是为了记录他节点的数据
boolean isVisted = false; //先设置为false
TreeNoder leftChild = null;
TreeNoder rightChild = null;
public TreeNoder(int key ,String data){
this.key = key;
this.data = data;
this.leftChild = null;
this.rightChild = null;
}
}
结果