二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”和“右子树”,左子树和右子树同时也是二叉树。
二叉树若直接定义可能会造成畸形,对树畸形的改进一般有两种方法,
- 方法一:平衡二叉树。
- 方法二:红黑树。
对平衡二叉树的定义:左右子树的高度相差不超过1。
调整方法:http://blog.youkuaiyun.com/a454042522/article/details/8591421
下面通过平衡二叉树方法写一棵树:
//递归定义法
//递归定义法中将每个节点看成一颗二叉树
class BiTree{
private int data;//数据
private BiTree left;//左子树
private BiTree right;//又子树
private int balance = 0;//平衡因子,避免树畸形
public BiTree(int data){
this.data = data;
}
public void calcu_balance(){//计算平衡因子
int leftH = left==null ? 0 : left.getHeight();
int rightH = right==null ? 0 : right.getHeight();
balance = leftH-rightH;
}
public BiTree add(BiTree biTrees){//添加二叉树
BiTree root = this;
if(biTrees.data < data){//如果要添加的数据小于当前节点数据,就添加到左子树
if(left == null){//如果左子树为空,直接添加
left = biTrees;
}else{//否者递归调用。返回新节点
left = left.add(biTrees);
}
}else{//如果要添加的数据大于当前节点数据,就添加到右子树
if(right == null){
right = biTrees;
}else{
right = right.add(biTrees);
}
}
calcu_balance();//添加完成之后重新计算平衡
if(balance>2){//左边太重
if(left.getBalance()>0){
root = adjustLL();
}
else{
root = adjustLR();
}
}
if(balance<-2){
if(right.getBalance()<0){
root = adjustRR();
}else{
root = adjustRL();
}
}
calcu_balance();
return root;
}
//返回树显示的高度
public int getHeight(){
int h = 2;
int hleft = left==null? 0 : left.getHeight();
int rleft = right==null? 0 : right.getHeight();
return h + Math.max(hleft, rleft);
}
//返回树的宽度
public int getWidth(){
int w = (""+data).length();
if(left!=null){
w += left.getWidth();
}
if(right!=null){
w += right.getWidth();
}
return w;
}
public int getBalance(){
return balance;
}
//调整LL型,进行右旋
private BiTree adjustLL(){
BiTree root = left;//将左子树纪录为根
left = root.right;//将原来根的右边挂在新根的左边
root.right = this;//根的右边等于自身
return root;
}
private BiTree adjustRR(){
BiTree root = right;
right = root.left;
root.left = this;
return root;
}
private BiTree adjustLR(){//调整LR型,先左旋再右旋
left = left.adjustRR();
return adjustLL();
}
private BiTree adjustRL(){
right = right.adjustLL();
return adjustRR();
}
//将二叉树结构打印出来
public void show(){
char[][] buf = new char[getHeight()][getWidth()];
printBuf(buf,0,0);
showBuf(buf);
}
private void showBuf(char[][] buf) {
for(int i=0; i<buf.length; i++){
for(int j=0; j<buf[i].length; j++){
System.out.print(buf[i][j]==0?' ':buf[i][j]);
}System.out.println();
}
}
private void printBuf(char[][] buf, int i, int j) {
String sv = "" + data;
int p1 = left==null ? i : left.getRootPos(i);
int p2 = getRootPos(i);
int p3 = right==null ? p2 : right.getRootPos(p2+sv.length());
buf[j][p2] = '|';
for(int k = p1; k<=p3; k++){
buf[j+1][k] = '-';
}
for(int k=0; k<sv.length(); k++){
buf[j+1][p2+k] = sv.charAt(k);
}
if(p1<p2){
buf[j+1][p1] = '/';
}
if(p3>p2){
buf[j+1][p3] = '\\';
}
if(left!=null){
left.printBuf(buf, i, j+2);
}
if(right!=null){
right.printBuf(buf, p2+sv.length(), j+2);
}
}
private int getRootPos(int i) {
return left==null ? i :i+left.getWidth();
}
//中序遍历
public void midTrav(){
if(left !=null){//如果左子树不为空,左子树进行中序遍历
left.midTrav();
}
System.out.print(data+" ");
if(right != null){//如果右子树不为空,右子树进行中序遍历
right.midTrav();
}
}
//前序遍历
public void preTrav(){
System.out.print(data+" ");
if(left !=null){//如果左子树不为空,左子树进行前序遍历
left.preTrav();
}
if(right != null){//如果右子树不为空,右子树进行前序遍历
right.preTrav();
}
}
//后序遍历
public void postTrav(){
if(left !=null){//如果左子树不为空,左子树进行后序遍历
left.postTrav();
}
if(right != null){//如果右子树不为空,右子树进行后序遍历
right.postTrav();
}
System.out.print(data+" ");
}
}
public class Tree {
public static void main(String[] args) {
BiTree root = new BiTree(10);
root = root.add(new BiTree(20));
root = root.add(new BiTree(30));
root = root.add(new BiTree(40));
root = root.add(new BiTree(50));
root = root.add(new BiTree(60));
root = root.add(new BiTree(70));
root = root.add(new BiTree(80));
/*root.midTrav();
System.out.println();
root.preTrav();
System.out.println();
root.postTrav();*/
root.show();
}
}
二叉树的打印结果:
|
/---40--\
| |
/-20\ /-60\
| | | |
10 30 50 70\
|
80