数据结构与算法
树
刚学过“树”这种数据结构,现在呈上一种典型的树——二叉树的实现及相关操作。
代码如下:
package NineWeek;
import java.util.*;
public class Tree {
public Tree left;
public Tree right;
public Object value;
public Tree(Object value){this.value=value;}
public Tree(){}
//以下是基本方法
/**
* 增加左子树
*
* @param value
*/
public void addLeft(Object value){
Tree leftChildren=new Tree(value);
this.left=leftChildren;
}
/**
* 增加右子树
*
* @param value
*/
public void addRight(Object value){
Tree rightChildren=new Tree(value);
this.right=rightChildren;
}
@Override
public boolean equals(Object obj){
if(!(obj instanceof Tree)) return false;
return this.value.equals(((Tree) obj).value);
}
@Override
public int hashCode(){
return this.value.hashCode();
}
@Override
public String toString(){
return this.value==null ? "" : String.valueOf(this.value);
}
//以下是功能方法(函数)
/**
* getTreeNum: 判断树中节点个数
*
* @param root 根节点
*
* @return int 返回类型
*/
public int getTreeNum(Tree root){
return (root==null) ? 0 : getTreeNum(root.left)+getTreeNum(root.right)+1;
}
/**
* getTreeDepth:返回树的深度
*
* @param root
*
* @return 树的深度
*/
public int getTreeDepth(Tree root){
return (root==null) ? 0 : Math.max(getTreeDepth(root.left)+1, getTreeDepth(root.right)+1);
}
/**
* visitNode: 访问node节点
*
* @param node void 返回类型
*/
private void visitNode(Tree node){
System.out.println(node.value+"\t");
}
/**
* preOrderTravel:前序遍历
*
* @param root 根节点
*/
public void preOrderTravel(Tree root){
if(root==null) return;
visitNode(root);
preOrderTravel(root.left);
preOrderTravel(root.right);
}
/**
* 中序遍历
*
* @param root 根节点
*/
public void midOrderTravel(Tree root){
if(root==null) return;
midOrderTravel(root.left);
visitNode(root);
midOrderTravel(root.right);
}
/**
* backOrderTravel: 后序遍历
*
* @param root 根节点
*/
public void backOrderTravel(Tree root){
if(root==null) return;
backOrderTravel(root.left);
backOrderTravel(root.right);
visitNode(root);
}
/**
* 分层遍历
*
* @param root 根节点
*/
public void levelTravel(Tree root){
Queue<Tree> q=new LinkedList<Tree>();
q.offer(root);
while(!q.isEmpty()){
Tree temp=q.poll();
visitNode(temp);
if(temp.left!=null)
q.offer(temp.left);
if(temp.right!=null)
q.offer(temp.right);
}
}
/**
* 求第k层节点个数
*
* @param root 根节点
*
* @param k 层数(从0开始)
*
* @return 节点个数
*/
public int getNumFromLevelK(Tree root, int k){
if(root==null||k<0) return 0;
if(k==0) return 1;
return getNumFromLevelK(root.left, k-1)+getNumFromLevelK(root.right, k-1);
}
/**
* getLeafNum: 求二叉树中叶子节点的个数
*
* @param root
* @return int 返回类型
*/
public int getLeafNum(Tree root){
if(root==null) return 0;
if(root.left==null&&root.right==null) return 1;
return getLeafNum(root.left)+getLeafNum(root.right);
}
/**
* 交换某节点下的左右子树
*
* @param root 目标节点
*
* @return 树
*/
public Tree exchange(Tree root){
if(root==null) return null;
Tree le=root.left;
root.left=root.right;
root.right=le;
return root;
}
/**
* 查看node是否是root的子节点
*
* @param root
*
* @param node
*
* @return
*/
public boolean nodeIsChild(Tree root, Tree node){
if(root==null||node==null) return false;
if(root==node) return true;
return nodeIsChild(root.left, node)||nodeIsChild(root.right, node);
}
/**
* 返回两个节点lnode和rnode的最近根节点
*
* @param root 根节点
*
* @param lnode节点1
*
* @param rnode节点2
*
* @return 最近公共父节点
*/
public Tree findAllFatherNode(Tree root, Tree lnode, Tree rnode){
if(root==lnode||root==rnode) return root;
if(root==null||lnode==null||rnode==null) return null;
// 如果lNode是左子树的节点
if(nodeIsChild(root.left, lnode)){
if(nodeIsChild(root.right, rnode)) return root;
else return findAllFatherNode(root.left, lnode, rnode);
}
else{
if(nodeIsChild(root.left, rnode)) return root;
else return findAllFatherNode(root.right, lnode, rnode);
}
}
/**
* 根据前序和中序构建二叉树
*
* @param pre前序序列
*
* @param mid中序序列
*
* @return二叉树
*/
public Tree getTreeFromPre_Mid(List<Integer> pre, List<Integer> mid){
if(pre==null||mid==null||pre.size()==0||mid.size()==0) return null;
if(pre.size()==1) return new Tree(pre.get(0));
// 找出根节点在中序中的位置
Tree root = new Tree(pre.get(0));
int index=0;
// 构建左子树的前序
while(!mid.get(index++).equals(pre.get(0))){}
// 构建左子树的前序
List<Integer> preLeft=new ArrayList<Integer>(index);
// 左子树的中序
List<Integer> midLeft=new ArrayList<Integer>(index);
for(int i=0;i<index;i++) preLeft.add(pre.get(i));
for(int i=0;i<index-1;i++) midLeft.add(mid.get(i));
// 重建左子树
root.left=getTreeFromPre_Mid(preLeft, midLeft);
// 右子树的前序
List<Integer> preRight=new ArrayList<Integer>(pre.size() - index - 1);
// 右子树的中序
List<Integer> midRight=new ArrayList<Integer>(pre.size() - index - 1);
for(int i=0;i<=pre.size()-index-1;i++) preRight.add(pre.get(index+1));
for(int i=0;i<=pre.size()-index-1;i++) midRight.add(mid.get(index+1));
// 重建→子树
root.right=getTreeFromPre_Mid(preRight, midRight);
return root;
}
public boolean equals(Tree node1, Tree node2){
if(node1==null&&node2==null) return true;
else if(node1==null||node2==null) return false;
boolean isEqual = node1.value.equals(node2.value);
boolean isLeftEqual = equals(node1.left, node2.left);
boolean isRightEqual = equals(node1.right, node2.right);
return isEqual && isLeftEqual && isRightEqual;
}
}
测试代码及结果:
package NineWeek;
import java.util.*;
public class TreeTest {
public static void main(String args){
Tree t=new Tree(1);
t.addLeft(2);
t.addRight(3);
t.left.addLeft(4);
t.left.addRight(5);
System.out.println("前序遍历:");
t.preOrderTravel(t);
System.out.println("\n中序遍历:");
t.midOrderTravel(t);
System.out.println("\n后序遍历:");
t.backOrderTravel(t);
System.out.println("\n层次遍历:");
t.levelTravel(t);
System.out.println();
System.out.println("树的深度:");
System.out.println(t.getTreeDepth(t));
System.out.println("叶子个数:");
System.out.println(t.getLeafNum(t));
System.out.println("节点个数:");
System.out.println(t.getTreeNum(t));
System.out.println("第二层节点数:");
System.out.println(t.getNumFromLevelK(t, 2));
System.out.println();
System.out.println("通过前序和中序构建树:");
List<Integer> pre = new ArrayList<Integer>();
pre.add(1);
pre.add(2);
pre.add(4);
pre.add(5);
pre.add(3);
List<Integer> mid = new ArrayList<Integer>();
mid.add(4);
mid.add(2);
mid.add(5);
mid.add(1);
mid.add(3);
Tree root=t.getTreeFromPre_Mid(pre, mid);
System.out.println("比较两树是否相等");
System.out.println(t.equals(t, root));
}
}
结果如下:
中序遍历测试:
4 2 5 1 3
前序遍历测试:
1 2 4 5 3
后序遍历测试:
4 5 2 3 1
层次遍历测试:
1 2 3 4 5
树的深度:3
树的叶子个数:3
树的节点个数:5
第2层节点个数为:2
通过前序和中序构建树测试:
1 2 3 4 5
构建的树比较测试:
true
【注】:部分空行可能显示有误,但不影响检查结果。