java中二叉树_二叉树(Java实现)

一、常见用语

1、逻辑结构:描述数据之间逻辑上的相关关系。分为线性结构(如,字符串),和非线性结构(如,树,图)。

2、物理结构:描述数据的存储结构,分为顺序结构(如,数组)和链式结构。

3、结点的度:一个节点子树(即分支)个数。

4、叶结点:也称为终端节点,指度为0的节点。

5、树的深度(高度):树中结点层次的最大值。

6、有序树:子树有先后次序之分(我的理解就是左右节点次序不可以颠倒)。

7、同构:将节点适当重命名,即可得两颗完全相同的树

8、孩子节点:一个节点的直接后继节点。

9、双亲节点:一个节点的直接前驱节点。

二、二叉树中的概念

1、二叉树:满足以下两个条件的树称为二叉树

①节点的度不可以超过2

②节点的孩子节点次序不可颠倒

2、满二叉树:每层得节点数都是满的,即2i-1

3、完全二叉树:节点1~n分别对应于满二叉树的节点1~n

4、完全二叉树的性质:

(1)若节点序号为i(i>1),则其双亲节点序号为i/2。(这里是整除)

(2)若节点序号为i(i>=1),则其左子节点序号为2i。

(3)若节点序号为i (i>=1),则其右子节点序号为2i+1。

三、二叉树的操作

1、二叉树节点的存储结构

public classTreeNode {

String data;

TreeNode LChild;

TreeNode RChild;

TreeNode(String data) {this.data =data;

}publicString toString() {returndata;

}

}

2、创建二叉树

使用前序遍历创建二叉树是比较合适,按照逻辑,总要先创建根节点在创建左右子树,总不能还没有创建根节点就把root.LChild传递出去吧。

private static String[] tree = {"A","B",".",".","C","D",".",".","."};private static int i = 0;//先序创建二叉树是比较合适的

TreeNode inOrderCreateBTree() {

TreeNode bt= null;

String s= tree[i++];if(s == ".") {returnbt;

}else{

bt= newTreeNode(s);

bt.LChild=inOrderCreateBTree();

bt.RChild=inOrderCreateBTree();returnbt;

}

}

可以用非递归的方式建树,但是难度还是挺大的。

3、先序遍历

递归方式:

//递归法前序遍历二叉树

voidpreOrderPrintBTree(TreeNode bt) {if(bt == null) {

System.out.print("." + " ");

}else{

System.out.print(bt+ " ");

preOrderPrintBTree(bt.LChild);

preOrderPrintBTree(bt.RChild);

}

}

基于栈的非递归方式:

跟着思路写就好:事实上这就是一个代码的模板,三种遍历的代码在结构上都是差不多的。

①指针移到最左子孙节点,边移变打印,边入栈(入栈是为了保存双亲节点,以便访问右子树)。

while(p != null) {

System.out.print(p+ " ");

stack.push(p);

p=p.LChild;if(p == null) {

System.out.print("." + " ");

}

}

②栈不空,就出栈,p指针指向右子树。

if(!stack.isEmpty()) {

p=stack.pop();

p=p.RChild;if(p == null) {

System.out.print("." + " ");

}

}

完整代码:

//基于栈的非递归法先序遍历二叉树

voidpreOrderPrintBTree1(TreeNode bt) {if(bt == null) {

System.out.println("null tree");

}

Stack stack = new Stack();

TreeNode p=bt;while(!stack.isEmpty() || p != null) {while(p != null) {

System.out.print(p+ " ");

stack.push(p);

p=p.LChild;if(p == null) {

System.out.print("." + " ");

}

}if(!stack.isEmpty()) {

p=stack.pop();

p=p.RChild;if(p == null) {

System.out.print("." + " ");

}

}

}

}

4、中序遍历

递归法:

voidinOrderPrint(TreeNode bt) {if(bt == null) {

System.out.print("." + " ");

}else{

inOrderPrint(bt.LChild);

System.out.print(bt+ " ");

inOrderPrint(bt.RChild);

}

}

非递归法:

前序遍历和中序遍历是查不多的,前者先打印后入栈,后者是先入栈后打印。

①p指针移到最左端,边移变入栈。

while(p != null) {

stack.push(p);

p=p.LChild;

}

②边出栈边打印,p指针指向右子树

if(!stack.isEmpty()) {

p=stack.pop();

System.out.print(p+ " ");

}

完整代码:

voidinOrderPrint1(TreeNode bt) {if(bt == null) {

System.out.println(".");

}else{

Stack stack = new Stack();

TreeNode p=bt;while(!stack.isEmpty() || p != null) {while(p != null) {

stack.push(p);

p=p.LChild;

}if(!stack.isEmpty()) {

p=stack.pop();

System.out.print(p+ " ");

}

}

}

}

5、后续遍历

递归:

voidpostOrderPrint(TreeNode bt) {if(bt == null) {

System.out.print("." + " ");

}else{

postOrderPrint(bt.LChild);

postOrderPrint(bt.RChild);

System.out.print(bt+ " ");

}

}

非递归:后续遍历的难点就在于要知道前一次访问的节点是左孩子还是右孩子,所以要设置一个前置指针pre。

①pcur指针移到最左端,边移边入栈

②pcur的有孩子被为null或者被访问过,则访问pcur,否则pcur要继续入栈,pcur指向其右孩子。

完整代码:

voidpostOrderPrint1(TreeNode bt) {if(bt == null) {

System.out.print("." + " ");

}else{

Stack stack = new Stack();

TreeNode pcur=bt;

TreeNode pre= null;while(pcur != null) {

stack.push(pcur);

pcur=pcur.LChild;

}while(!stack.isEmpty()) {

pcur=stack.pop();if(pcur.RChild == null || pcur.RChild ==pre) {

System.out.print(pcur+ " ");

pre=pcur;

}else{

stack.push(pcur);

pcur=pcur.RChild;while(pcur != null) {

stack.push(pcur);

pcur=pcur.LChild;

}

}

}

}

}

6、二叉树的其他操作

(1)打印叶子节点

//前序遍历打印叶子节点

public static voidpreprintLeaves(TreeNode bt) {if(bt == null) {

}else{if(bt.LChild == null && bt.RChild == null) {

System.out.print(bt+ " ");

}

preprintLeaves(bt.LChild);

preprintLeaves(bt.RChild);

}

}

(2)求树的深度

//先序遍历求二叉树的深度

public static int preTreeDepth(TreeNode bt, inth) {if(bt != null) {if(h > depth) depth =h;

preTreeDepth(bt.LChild,h+1);

preTreeDepth(bt.RChild,h+1);

}returndepth;

}//后续遍历求二叉树深度

public static intpostTreeDepth(TreeNode bt) {int hl = 0;int hr = 0;int max = 0;if(bt == null) {return 0;

}else{

hl=postTreeDepth(bt.LChild);

hr=postTreeDepth(bt.RChild);

max=Math.max(hr, hl);return max + 1;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值