您的位置:首页 > 其它

关于树的一些总结

2015-07-25 18:10 267 查看
最近学习java的相关内容,涉及到数据结构中树的一些操作,先总结一下,以后慢慢完善

树的主要操作有:

基本操作(添加,删除,查找一个结点)
遍历(前序,中序,后序,层序)
创建一颗树(根据前序遍历的格式;根据前序和中序遍历);销毁树
判断一颗树是否平衡;判断两棵树是否相等
获取树的高度和宽度
.等等。。。

代码如下:

/*定义树的结点*/
class BTNode{
char data;
BTNode leftNode;
BTNode rightNode;
public BTNode(){}
public BTNode(char data) {
this.data = data;
}
}
/**
* 定义树的数据结构
*/
public class BTree{
private BTNode root;
public BTree() {}
/*初始化根节点*/
public BTree(char rootData) {
this.root = new BTNode(rootData);
}

/*根据前序遍历创建树*/
public BTree(char[] arr){
this.arr = arr;
this.root = createTree();
}

//使用递归,查找一个结点
public BTNode search(BTNode root, char data){
BTNode temp = null;
if(root != null){
if (root.data == data) {
return root;
}else {
temp = search(root.leftNode, data);
if(temp == null)
return search(root.rightNode, data);
}
}
return temp;
}

//在指定的结点上增加一个结点,type为0时添加左结点,为1时添加右结点
public void add(char parentData, char data, int type){
BTNode node = new BTNode(),tempNode;
//找到parentData的结点
tempNode = search(root, parentData);
if(tempNode != null){
node.data = data;
if (type == 0)
tempNode.leftNode = node;
if (type == 1)
tempNode.rightNode = node;
}else {
System.out.println("找不到指定的结点!");
}
}

/**
* 清除树
* @param root
*/
public void clear(BTNode root){
if (root != null) {
clear(root.leftNode);
clear(root.rightNode);
root = null;
}
}
/**
* 层序遍历
* @param root
*/
private void levelInner(BTNode root){
//定义队列来存储各层的结点,maxlen各层最大结点数
BTNode[] temp = new BTNode[MAXLEN];
int head = 0, tail = 0;

BTNode t;
//入队
if (root != null ) {
tail = (tail + 1) % MAXLEN;
temp[tail] = root;
}
while(head != tail){
//处理结点
head = (head +1) % MAXLEN;
t = temp[head];
System.out.println("处理结点数据"+ t.data);
//添加结点
if (t.leftNode != null) {
temp[++tail % MAXLEN] = t.leftNode;
}
if (t.rightNode != null) {
temp[++ tail % MAXLEN] = t.rightNode;
}
}
}
//包装一下
public void levelOrder(){
levelInner(this.root);
}
/**
* 前序遍历
* @param root
*/
private void dlrInner(BTNode root){
if (root != null) {
System.out.println(root.data);
dlrInner(root.leftNode);
dlrInner(root.rightNode);
}
}
public void preOrder(){
dlrInner(this.root);
}
/**
* 中序遍历
* @param root
*/
private void ldrInner(BTNode root){
if (root != null) {
ldrInner(root.leftNode);
System.out.println(root.data);
ldrInner(root.rightNode);
}
}
public void inOrder(){
ldrInner(this.root);
}
/**
* 后序遍历
* @param root
*/
private void ltdInner(BTNode root){
if (root != null) {
ltdInner(root.leftNode);
ltdInner(root.rightNode);
System.out.println(root.data);
}
}
public void postOrder(){
ltdInner(this.root);
}

/*根据前序遍历格式创建一个树
1 2 4 6 0 0 7 0 0 5 8 0 0 9 0 0 3 0 0
要使用两个成员变量,如果用c实现更方便,可以传入指针创建*/
private char[] arr;
private int i;
private BTNode createTree(){
BTNode node = null;
if(i>=arr.length||arr[i] ==0){
i++;
return null;
}else{
node =  new BTNode(arr[i++]);
node.leftNode = createTree();
node.rightNode = createTree();
}
return  node;
}
//根据前序遍历和中序遍历创建一棵树,定义成静态类
private static BTNode createTreeInner(String preOrder,String inOrder, int len) throws Exception{
if(preOrder == null&& inOrder== null)
return null;
BTNode node = new BTNode(preOrder.charAt(0));
//在中序遍历中寻找根结点
int i =0;
while(preOrder.charAt(0)!=inOrder.charAt(i)){
i++;
if(i>=len) throw new Exception("Error");
}

//创建左子树
if(i>0)
node.leftNode = createTreeInner(preOrder.substring(1), inOrder, i);
//创建右子树
if(i<len-1)
node.rightNode = createTreeInner(preOrder.substring(i+1), inOrder.substring(i+1), len-i-1);
return node;
}
public static BTree createTree(String preOrder,String inOrder) throws Exception{
BTree btree = new BTree();
btree.setRoot(createTreeInner(preOrder, inOrder, inOrder.length()));
return btree;
}
/**
* 获取树的宽度
* @param root
* @return
*/
public int getWidth(BTNode root){
int currentCount = 1,count=0;
BTNode temp;
LinkedList<BTNode> ll = new LinkedList<BTNode>();
ll.offer(root);
while(currentCount!=0){
while(currentCount!=0){
temp = ll.poll();
if(temp.leftNode!=null){
ll.offer(temp.leftNode);
}
if(temp.rightNode != null){
ll.offer(temp.rightNode);
}
currentCount--;
}
currentCount = ll.size();
//保存最多的结点
if(currentCount>count)
count = currentCount;
}
return count;
}
/**
* 判断两棵树是否相同
* @param a
* @param b
* @return
*/
private boolean equalInner(BTNode a, BTNode b){
if(a==null&&b!=null||a!=null&&b==null)
return false;
else if(a!=null&&b!=null){
if(a.data != b.data){
return false;
}else if(!equalInner(a.leftNode, b.leftNode)){
return false;
}else if(!equalInner(a.rightNode, b.rightNode)){
return false;
}
}
return true;
}

public boolean equals(BTree tree){
if(equalInner(root, tree.getRoot())){
return true;
}
return false;
}

/**
* 获取树的深度
* @param root
* @return
*/
public int getDeep(BTNode root){
int deepleft ,deepright;
if (root == null) {
return 0;
}
deepleft = getDeep(root.leftNode);
deepright = getDeep(root.rightNode);
if (deepleft >= deepright) {
return ++deepleft;
}else{
return ++deepright;
}
}

/**
* 判断树是否是平衡树
* @param root
* @return
*/
//方法一:先获取树的高度,然后才判断,由高到底(效率不高,java可方便实现)
private boolean isBalanceInner(BTNode root){
if(root == null){
return true;
}
int leftHeight = getDeep(root.leftNode);
int rightHeight = getDeep(root.rightNode);
int diff = leftHeight - rightHeight;
if(diff>1||diff<-1){
return false;
}
return isBalanceInner(root.leftNode)&&isBalanceInner(root.rightNode);
}
//包装一下
public boolean isBalance(){
return isBalanceInner(this.root);
}

//方法二:利用后序遍历的特征,一次性获取,由低到高
//需要定义一个辅助类
private class Depth {
int height;
}
private boolean isBalanceInner(BTNode node,Depth d){
if(node==null){
d.height=0;
return true;
}
Depth right=new Depth();
Depth left = new Depth();
if(isBalanceInner(node.leftNode,left)&&isBalanceInner(node.rightNode,right)){
int diff = left.height-right.height;
if(diff<=1||diff>=-1){//绝对值小于等于1
//如果是平衡树,才有必要算深度,然后看上级是不是平衡树
d.height=left.height>right.height?left.height:right.height;
return true;
}
}
return false;
}
//包装一下
public boolean isBalance2(BTNode root){
return isBalanceInner(root,new Depth());
}
public BTNode getRoot(){
return this.root;
}
public void setRoot(BTNode root){
this.root = root;
}
}


说明:有的代码是参考c实现的,java和c在实现上确实有很多不同的地方,尤其是树的递归调用,java中不能引用基本变量,只能是对象,所以在实现上与c相比,不太方便

树的其他操作以后遇到再慢慢补上。。。。


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: