java实现二叉树_使用Java实现二叉树的添加,删除,获取以及遍历

package com.rainple.collections;/**

* 二叉树

* @param */

public class BinaryTree>{//根节点

private Entryroot;//数据量

private int size = 0;publicBinaryTree(){}/**

* 添加元素

* @param item 待添加元素

* @return 已添加元素*/

publicT put(T item){//每次添加数据的时候都是从根节点向下遍历

Entry t =root;

size++;if (t == null){//当前的叉树树的为空,将新节点设置为根节点,父节点为null

root = new Entry<>(item,null);returnroot.item;

}//自然排序结果,如果传入的数据小于当前节点返回-1,大于当前节点返回1,否则返回0

int ret = 0;//记录父节点

Entry p =t;while (t != null){//与当前节点比较

ret =item.compareTo(t.item);

p=t;//插入节点比当前节点小,把当前节点设置为左子节点,然后与左子比较,以此类推找到合适的位置

if (ret < 0)

t=t.left;//大于当前节点

else if (ret > 0)

t=t.right;else{//相等就把旧值覆盖掉

t.item =item;returnt.item;

}

}//创建新节点

Entry e = new Entry<>(item,p);//根据比较结果将新节点放入合适的位置

if (ret < 0)

p.left=e;elsep.right=e;returne.item;

}public voidprint(){

midIterator(root);

}/**

* 中序遍历

* @param e*/

public void midIterator(Entrye){if (e != null){

midIterator(e.left);

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

midIterator(e.right);

}

}/**

* 获取根节点

* @return 根节点*/

public Entry getRoot(){returnroot;}/**

* 前序遍历

* @param e 开始遍历元素*/

public void prevIterator(Entrye){if (e != null) {

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

prevIterator(e.left);

prevIterator(e.right);

}

}/**

* 后续遍历

* @param e 开始遍历元素*/

public void subIterator(Entrye){if (e != null) {

subIterator(e.left);

subIterator(e.right);

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

}

}/**

* 获取节点节点

* @param item 获取节点

* @return 获取到的节点,可能为null*/

private EntrygetEntry(T item){

Entry t =root;intret;//从根节点开始遍历

for (;t != null;){

ret=item.compareTo(t.item);if (ret < 0)

t=t.left;else if (ret > 0)

t=t.right;else

returnt;

}return null;

}/**

* 判断是否存在该元素

* @param item 查找元素

* @return 结果*/

publicboolean contains(T item){return getEntry(item) != null;

}/**

* 删除元素

* 删除元素如果细分的话,可以分为4中:没有子节点,只有左节点,只有右节点,有两个子节点

* 1)没有子节点这种情况比较简单,直接删除就可以了

* 2)只有左节点或右节点,这两种情况处理方式是一致的,只是方向相反,所以在一起讲了,

* 将删除节点的父节点的左节点(右节点)指向删除节点的子节点,将左节点(右节点)指向删除节点的父节点

* 3)有两个子节点,这种情况相对来说比较复杂一点:

* 找到删除节点的前驱节点或后继节点,然后将前驱或后继节点的值赋给删除节点,然后将前驱或后继节点删除。本质是删除前驱或后继节点

* 前驱节点的特点:

* 1)删除的左子节点没有右子节点,那么左子节点即为前驱节点

* 2)删除节点的左子节点有右子节点,那么最右边的最后一个节点即为前驱节点

* 后继节点的特点:

* 与前驱节点刚好相反,总是右子节点,或则右子节点的最左子节点;例如:删除节点为c ,那么前驱节点为 m,后继节点为n

* a

* / \

* b c

* / \ / \

* d e f g

* / \ / \ / \ / \

* @param item 删除元素 h i j k l m n o

* @return 删除结果*/

publicboolean remove(T item){//获取删除节点

Entry delEntry =getEntry(item);if (delEntry == null) return false;//删除节点的父节点

Entry p =delEntry.parent;

size--;//情况1:没有子节点

if (delEntry.left == null && delEntry.right == null){//删除节点为根节点

if (delEntry ==root){

root= null;

}else {//非根节点//删除的是父节点的左节点

if (delEntry ==p.left){

p.left= null;

}else {//删除右节点

p.right = null;

}

}//情况2:删除的节点只有左节点

}else if (delEntry.right == null){

Entry lc =delEntry.left;//删除的节点为根节点,将删除节点的左节点设置成根节点

if (p == null) {

lc.parent= null;

root=lc;

}else {//非根节点

if (delEntry == p.left){//删除左节点

p.left =lc;

}else {//删除右节点

p.right =lc;

}

lc.parent=p;

}//情况3:删除节点只有右节点

}else if (delEntry.left == null){

Entry rc =delEntry.right;//删除根节点

if (p == null) {

rc.parent= null;

root=rc;

}else {//删除非根节点

if (delEntry ==p.left)

p.left=rc;elsep.right=rc;

rc.parent=p;

}//情况4:删除节点有两个子节点

}else {//有两个节点,找到后继节点,将值赋给删除节点,然后将后继节点删除掉即可

Entry successor = successor(delEntry);//获取到后继节点

delEntry.item =successor.item;//后继节点为右子节点

if (delEntry.right ==successor){//右子节点有右子节点

if (successor.right != null) {

delEntry.right=successor.right;

successor.right.parent=delEntry;

}else {//右子节点没有子节点

delEntry.right = null;

}

}else {//后继节点必定是左节点

successor.parent.left = null;

}return true;

}//让gc回收

delEntry.parent = null;

delEntry.left= null;

delEntry.right= null;return true;

}/**

* 查找后继节点

* @param delEntry 删除节点

* @return 后继节点*/

private Entry successor(EntrydelEntry) {

Entry r = delEntry.right;//r节点必定不为空

while (r.left != null){

r=r.left;

}returnr;

}public int size(){returnsize;}public boolean isEmpty(){return size == 0;}public voidclear(){

clear(getRoot());

root= null;

}private void clear(Entrye){if (e != null){

clear(e.left);

e.left= null;

clear(e.right);

e.right= null;

}

}static final class Entry>{//保存的数据

privateT item;//左子树

private Entryleft;//右子树

private Entryright;//父节点

private Entryparent;

Entry(T item,Entryparent){this.item =item;this.parent =parent;

}

}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值