java二叉查找树遍历_java:数据结构(四)二叉查找树以及树的三种遍历

本文介绍了Java中二叉查找树的实现,包括树的结构、插入和删除操作。同时,详细讲解了树的前序、中序、后序遍历以及层序遍历的实现方法。最后通过示例展示了如何查找树中的最小和最大元素以及删除节点。
摘要由CSDN通过智能技术生成

@

二叉树模型

二叉树是树的一种应用,一个节点可以有两个孩子:左孩子,右孩子,并且除了根节点以外每个节点都有一个父节点。当然这种简单的二叉树不能解决让树保持平衡状态,例如你一直往树的左边添加元素,就会导致查找效率的减慢。,如何解决这个问题,下一篇文章再说。

二叉树的实现

二叉树的实现类

import java.util.LinkedList;

/**

* 二叉查找树

* @param 泛型节点

*/

public class BinaryTree implements Tree {

/**

* @param root 根节点

*/

private Node root;

/**

* 内部类

* 继承Comparable类来比较泛型的大小

* 如果泛型是一个包含个多基本类型的对象,你需要重写compareTo方法

* @param 泛型类型的节点

*/

private class Node {

E data;

Node left;

Node right;

public void setLeft(Node left) {

this.left = left;

}

public void setRight(Node right) {

this.right = right;

}

public int getNum() {

return num;

}

public void setNum(int num) {

this.num = num;

}

int num;

public Node getLeft() {

return left;

}

public Node getRight() {

return right;

}

public Node(E data){

this.data=data;

}

public Node(E data, Node next, Node pre) {

this.data = data;

this.left = next;

this.right = pre;

}

public Node(){

left=null;

right=null;

data=null;

num=1;

}

public E getData() {

return data;

}

public void setData(E data) {

this.data = data;

}

}

/**

* 判空方法

* @return true 树为空 false 树不为空

*/

@Override

public boolean isEmpty() {

if(root==null){

return true;

}else{

return false;

}

}

/**

* 使树为空

* 个人理解:

* 树中其他节点有实例对象存储在实例池中

* 根节点不仅有实例对象,而且还要引用类型,存在java栈的本地变量表中

* 之间使根节点为NULL

*/

@Override

public void makeEmpty() {

root=null;

}

/**

* 判断某个泛型类型的节点在树中

* @param p 泛型类型

* @return true 包含在节点中 false 不包含

*/

@Override

public boolean contains(E p) {

return contain(p,root);

}

/**

* contains方法的具体实现

* 采用递归实现

* @param p 需要判断是否存在书中泛型元素

* @param r 树中的节点

* @return true 包含 false 不包含

*/

private boolean contain(E p,Node r){

Node temp=root;

if(root==null){

return false;

}else{

if(temp.getData().compareTo(p)>0){

contain(p,temp.getLeft());

}else if(temp.getData().compareTo(p)<0){

contain(p,temp.getRight());

}else if(temp.getData().compareTo(p)==0&&temp.num>0){

return true;

}

}

return false;

}

/**

* 找到树中最小的元素

* @return 树中最小的元素

*/

@Override

public E findMin() {

if(isEmpty()){

System.out.println("树为空");

}else {

/**

* 因为采用懒惰删除,所以树中最小的元素不仅要是最左面的哪一个

* 而且还要是num>0的哪一个

*/

Node p = root;

Node temp = root;

while (p.getLeft() != null) {

p = p.getLeft();

if (p.num > 0) {

temp = p;

}

}

return temp.getData();

}

throw new NullPointerException();

}

/**

* 找到树中最大的元素

* 和寻找最小的原理一样

* @return 树中最大的元素

*/

@Override

public E findMax() {

if(isEmpty()){

System.out.println("树为空");

}else {

Node p = root;

Node temp = root;

while (p.getRight() != null) {

p = p.getRight();

if (p.num > 0) {

temp = p;

}

}

return temp.getData();

}

throw new NullPointerException();

}

/**

* 树的前序遍历

* 根左右

*/

@Override

public void preTraversal() {

System.out.print("前序遍历:");

preTraversal(root);

System.out.println();

}

/**

* 前序遍历的具体实现方法

* @param p 使用递归时进入下一个节点

*/

private void preTraversal(Node p) {

if(isEmpty()){

System.out.println("树为空");

}else {

if (p.num > 0) {

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

}

if (p.getLeft() != null) {

preTraversal(p.getLeft());

}

if (p.getRight() != null) {

preTraversal(p.getRight());

}

return;

}

}

/**

* 树的层序遍历

* 即从根开始一层一层的遍历

*/

public void seqTraverse(){

if(isEmpty()){

System.out.println("树为空");

}else {

System.out.print("层序遍历:");

LinkedList> temp = new LinkedList<>();

Node p = root;

temp.add(p);

while (!temp.isEmpty()) {

Node a = temp.pop();

if (a.num > 0) {

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

}

if (a.getLeft() != null) {

temp.add(a.getLeft());

}

if (a.getRight() != null) {

temp.add(a.getRight());

}

}

System.out.println();

}

}

/**

* 后序遍历的实现方法

* @param p 使用递归时进入下一个节点

*/

private void posTraversal(Node p) {

if(isEmpty()){

System.out.println("树为空");

}else {

if (p.getLeft() != null) {

posTraversal(p.getLeft());

}

if (p.getRight() != null) {

posTraversal(p.getRight());

}

if (p.num > 0) {

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

}

return;

}

}

/**

* 中序遍历的实现方法

* @param p 使用递归时进入下一个节点

*/

private void cenTraversal(Node p) {

if(isEmpty()){

System.out.println("树为空");

}else {

if (p.getLeft() != null) {

cenTraversal(p.getLeft());

}

if (p.num > 0) {

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

}

if (p.getRight() != null) {

cenTraversal(p.getRight());

}

return;

}

}

/**

* 树的后序遍历

* 左右根

*/

@Override

public void posTraversal() {

System.out.print("后序遍历:");

posTraversal(root);

System.out.println();

}

/**

* 树的中序遍历

* 左根右

*/

@Override

public void cenTraversal() {

System.out.print("中序遍历:");

cenTraversal(root);

System.out.println();

}

/**

* 向树中插入元素

* @param p 待插入的元素

*/

@Override

public void insert(E p) {

/**

* 主要为了将num加一

*/

Node temp=new Node<>(p);

temp.num++;

/**

* 根为空,就给根赋值

*/

if(root==null) {

root=temp;

}else{

/**

*如果元素小于当前的d元素就往左递归

* 反之就向右递归

* 如果相等就num加一

*/

Node d=root;

while (d!=null){

if(p.compareTo(d.getData())<0){

if(d.getLeft()==null){

d.setLeft(temp);

break;

}

d=d.getLeft();

}else if(p.compareTo(d.getData())>0){

if(d.getRight()==null){

d.setRight(temp);

break;

}

d=d.getRight();

}else{

d.num++;

}

}

}

}

/**

*删除树中的一个节点

* 采用懒惰删除对num的节点进行减一

* @param p 需要删除的内容

*/

@Override

public void remove(E p) {

removePri(p,root);

}

private void removePri(E p,Node r){

Node temp=r;

if(temp.getData().compareTo(p)>0){

removePri(p,temp.getLeft());

}else if(temp.getData().compareTo(p)<0){

removePri(p,temp.getRight());

}else {

temp.num--;

}

}

}

接口的类

/**

* 树的接口

* @param 泛型的类型

*/

public interface Tree {

/**

* 判空函数

* @return true 树为空 false 树不为空

*/

boolean isEmpty();

/**

* 使树为空

*/

void makeEmpty();

/**

* 检查书中是否包含p这个元素

* @param p 泛型元素

* @return true 包含 false 不包含

*/

boolean contains(E p);

/**

* 找到树中最小元素

* @return 最小的元素

*/

E findMin();

/**

* 找到树中最大元素

* @return 最大的元素

*/

E findMax();

/**

* 前序遍历

*/

void preTraversal();

/**

* 后序遍历

*/

void posTraversal();

/**

* 中序遍历

* 森林里没有中序遍历,森林无法判断哪个是中间

* 所以可以不实现

*/

default void cenTraversal() {

}

/**

* 插入元素

* @param p 待插入的元素

*/

void insert(E p);

/**

* 删除方法

* @param p 待删除的元素

*/

void remove(E p);

}

对于代码的测试

import java.util.Stack;

public class Main {

public static void main(String[] args) {

BinaryTree dd=new BinaryTree<>();

dd.insert(4);

dd.insert(2);

dd.insert(3);

dd.insert(1);

dd.insert(6);

dd.insert(5);

dd.insert(7);

// dd.preTraversal();

//dd.cenTraversal();

// dd.posTraversal();

// dd.seqTraverse();

System.out.println(dd.findMin()); ;

System.out.println(dd.findMax());

dd.remove(2);

dd.remove(6);

}

}

如上图的代码构成了如下的树:

graph LR

A((4)) --> B((2))

A --> C((6))

B-->d((1))

B-->e((3))

C-->g((5))

C-->j((7))调用findMax和findMin方法结果如下:

7e4c2bd22a51d52bdb60302020d1b547.png

调用remove方法前后的区别

-调用前

d1e991fc17d194829cb11f4d4d583add.png

调用后:

fe2232069be2b2669b5c861f5a1d9ba5.png

可见被删除的元素没有输出

树的三种遍历

四种遍历分别是先序遍历、中序遍历、后序遍历、层序遍历

先序遍历就是:对节点的除了工作是在它的诸儿子节点被处理前进行的,也就是说先访问根再访问左子树然后访问右子树。

中序遍历:对节点的除了工作是在它的左儿子节点被处理后进行的,也就是说先访问左节点再访问根节点然后访问右节点。

后序遍历:对节点的除了工作是在它的诸儿子节点被处理后进行的,也就是说先访问左再访问根子树然后访问右子树。

层序遍历:和前三种遍历方式不一样,层序遍历需要借用队列,从根节点读入,然后出队,只要出队的元素有左节点,左节点就入队,若还有右节点,右节点就入队,直到队列为空。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值