一.二叉树的创建算法
博主之所一把这两个算法放一起,原因是这两个算法对于我们写二叉树来说太重要了,创建算法写得好的话可以省很多事儿,当然这儿的创建指的是二叉树的首次创建,大部分二叉树创建的时候需要我们输入很多节点进去。
1.二叉树输入格式
要想计算机知道我们输入的是什么意思那我们的输入就一定得有一定的格式,下面我就来介绍一种相对于来说比较简单的格式
那就是是用括号表示一棵二叉树如(左子树,右子树)子树里面套子树如A(B(D,E),C(F,G(H,I)))表示的就是以下子树
图画的不好,我电脑上也没装啥画图软件,按照这种格式输入然后我们的程序只需要解析格式就能创建出相应的二叉树了。
public static BinTree createBTree(String str){//BinTree就是二叉树类BinNode就是二叉树的节 点类
char[] arr = str.toCharArray();
//这是字符型二叉树,其他的与此类似只需要把数组写成字符串类型
BinNode[] BT = new BinNode[str.length()];//定义栈
BinNode p =null;
int top = -1;//栈顶游标
int k = 0;
BinTree tree = new BinTree(arr[0]+ "");//创建二叉树
p = tree.tree;//获取根节点
for(int i=1;i<arr.length;i++){
switch(arr[i]){
case '(':{
top++;
BT[top] = p;
k =1;//表示下一个为左子树
break;
}
case ')':{
top--;
break;
}
case ',':{
k = 2;//下一个为右子树
break;
}
default:{//创建节点
p = new BinNode(arr[i] + "");
if( k ==1){
BT[top].lchild = p;
}
if(k==2){
BT[top].rchild = p;
}
break;
}
}
}
return tree;
}
class BinNode<E>{//二叉树节点类
BinNode lchild;
BinNode rchild;
E data;
public BinNode(){
}
public BinNode(E e){
this.data = e;
}
}
如果二叉树不是这种字符型,可以截取字符串(从第一个字符到逗号)。
(二).二叉树的输出算法(按层输出,第一层在最上面)
1.效果展示(第一个是高度为4的满二叉树,第二幅图为前面实例的二叉树)
上面这幅图是计算间距的依据,最左边的距离和右边是不一样的但是都有相应的递推公式。最左边就是总层数减去当前层的二次幂再加一,如:第一层就为2^(4-1)+1=9.右边就简单了,第一行可以直接换行,其他的就是2^(deep-dept+1);
下面贴出代码
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package datastruct.BinTree;
import datastruct.LinkQueue.LinkQueue;
/**
*
* @author jester
*/
public class BinTree<E>{
public static BinNode root;
private BinNode<E> tree;
public BinTree(E e){
root = this.tree = new BinNode<E>(e);
}
public static BinTree createBTree(String str){
char[] arr = str.toCharArray();
BinNode[] BT = new BinNode[str.length()];
BinNode p =null;
int top = -1;
int k = 0;
BinTree tree = new BinTree(arr[0]+ "");
p = tree.tree;
for(int i=1;i<arr.length;i++){
switch(arr[i]){
case '(':{
top++;
BT[top] = p;
k =1;
break;
}
case ')':{
top--;
break;
}
case ',':{
k = 2;
break;
}
default:{
p = new BinNode(arr[i] + "");
if( k ==1){
BT[top].lchild = p;
}
if(k==2){
BT[top].rchild = p;
}
break;
}
}
}
return tree;
}
public boolean lchild(){//
if(tree.lchild==null){
return false;
}
this.tree = tree.lchild;
return true;
}
public boolean rchild(){//
if(tree.rchild==null){
return false;
}
this.tree = tree.rchild;
return true;
}
public boolean insertLchild(E e){//
if(this.tree==null){
return false;
}
return tree.addNode(e, 1) != null;
}
public boolean insertRchild(E e){//
if(this.tree==null){
return false;
}
return tree.addNode(e, 2) != null;
}
public void backToRoot(){//
this.tree = root;
}
public E getData(){//
return this.tree.data;
}
public int deepth(BinNode b){
if(b==null){
return 0;
}else{
int l = deepth(b.lchild);
int r = deepth(b.rchild);
return l>r?l+1:r+1;
}
}
public void print(){ //按层打印二叉树
BinNode temp = root; //存每次处理的节点
int deep = deepth(this.tree); //计算二叉树的最大深度,为整颗树的定位做准备
int MaxSize = (int)Math.pow(2, deep);//这就是最大深度的作用
BinNode[] Qu = new BinNode[MaxSize];
int dept = 0; //记录对应第几层
int last = 0; //记录每层最后一个节点
int front,rear; //队列的头和尾
front = rear = 0;
if(this.tree==null){
return;
}
dept = 1;
rear++;
Qu[rear] = temp;
last = rear;
boolean bool = false; //记录还有没有必要继续访问,当该层都没有子树的时候就结束访问
while(rear!=front){
front = (front +1)%MaxSize;
temp = Qu[front];
if(temp!=null&&(temp.lchild!=null||temp.rchild!=null)){
bool = true;
}
if(temp!=null){//避免为空
rear = (rear+1)%MaxSize;
Qu[rear] = temp.lchild;
rear = (rear+1)%MaxSize;
Qu[rear] = temp.rchild;
}else{ //为空的时候也得用空对象站位
rear = (rear+1)%MaxSize;
Qu[rear] = null;
rear = (rear+1)%MaxSize;
Qu[rear] = null;
}
if(front==last){ //结束行检查。。。注意里面的打印次序错一个都不行
if(!bool){
printData(temp); //打印最后一个元素
return;
}
last = rear;
bool = false;
if(dept==1){ //第一行比较特殊所以区分开
for(int j=0;j<Math.pow(2, deep-dept)+1;j++){//这个循环次数见草图
System.out.print("\t");
}
}
printData(temp);
System.out.println("");
System.out.println("");
System.out.println("");
dept++;
for(int j=0;j<Math.pow(2, deep-dept)+1;j++){
System.out.print("\t");
}
}else{
printData(temp);
for(int k=0;k<Math.pow(2, deep-dept+1);k++){
System.out.print("\t");
}
}
}
}
public void printData(BinNode _data){//避免节点为空
if(_data==null){
System.out.print(" ");
return;
}
System.out.print(_data.data);
}
public BinNode getNode(){
return this.tree;
}
}
class BinNode<E>{
BinNode lchild;
BinNode rchild;
E data;
public BinNode(){
}
public BinNode(E e){
this.data = e;
}
public BinNode addNode(E e,int rOrl){
if(rOrl==1){
return this.lchild = new BinNode(e);
}else if(rOrl==2){
return this.rchild = new BinNode(e);
}
return null;
}
}
我把整个类都粘贴出来了,就是怕中间有函数调用我又没把函数贴出来,其他没用的你们可以删掉。
下面是主函数的代码,
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package datastruct.BinTree;
/**
*
* @author jester
*/
public class BTreeTest {
public static void main(String[] args) {
String tree1 = "A(B(D(H,I),E(J,K)),C(F(L,M),G(N,O)))";
BinTree BTree1 = BinTree.createBTree(tree1);
System.out.println(BTree1.deepth(BTree1.getNode()));
BTree1.print();
System.out.println("");
System.out.println("");
System.out.println("");
String tree2 = "A(B(D,E),C(F,G(H,I)))";
BinTree BTree2 = BinTree.createBTree(tree2);
System.out.println(BTree2.deepth(BTree2.getNode()));
BTree2.print();
}
}