数据结构学习-二叉查找树(实现并测试)

定义:只有两个子节点的树称为二叉树

满二叉树:如果一个二叉树,每一层的结点树都达到最大值,则为满二叉树

完全二叉树:上一层未满的情况下不允许插入元素

 

1.结点类的实现:根结点、左子结点、右子结点

 

public class BinaryNode<Key extends Comparable<Key>,Value> {
   
public BinaryNode left;
    public
BinaryNode right;
    public
Key key;
    public
Value value;

    public
BinaryNode(BinaryNode left, BinaryNode right, Key key, Value value) {
       
this.left = left;
        this
.right = right;
        this
.key = key;
        this
.value = value;
   
}
}

 

2.二叉查找树的API设计:

类名

BinaryTree<Key extends Comparable<Key>>,Value value>

此处继承是为了之后进行排序

构造方法

Public BinaryTree();

成员变量

Private Node root;//根结点

Private int length;//结点的个数

成员方法

1. public void put(key,value);//插入键值对

2. public Node put(Node x,key,value);//指定x树中插入键值对

3. public value get(key);//获取键对应的值

4. public value get(Node x,key);//删除指定树上键对应的值

5. public void delete(key);//

6. public value delete (Node x,key);//删除指定树上键对应的值

 

 

3.代码实现

增加:

 

/**
 *
插入键值对
 
* @param key
 
* @param value
 
*/
public void put(Key key, Value value){
    root =
this.put(root,key,value);
}

/**
 *
指定x树中插入键值对
 
* @param x
 
* @param key
 
* @param value
 
*/
public BinaryNode put(BinaryNode x,Key key, Value value){
   
//如果x空,即为key-value
   
if(x == null){
       
length++;
        return new
BinaryNode(null,null,key,value);
   
}

   
//如果x空,判keyroot.key的大小,
   
//key < root.key
   
if (key.compareTo((Key) x.key) < 0){
        x.
left = put(x.left,key,value);
   
}
   
//key > root.key
   
if (key.compareTo((Key) x.key) > 0){
        x.
right = put(x.right,key,value);
   
}

   
if (key.compareTo((Key) x.key) == 0){
        x.
value = value;
   
}
   
return x;
}

 

※注意:

1.在put方法中,root根节点没有及时更新

 

2.结点实体类无需继承Comparable接口,而二叉树需要

 

 

获取:

 

/**
 *
获取指定key的元素
 
* @param key
 
* @return
 
*/

public Value get(Key key){
   
return get(root,key);
}

/**
 *
获取指定二叉树的元素
 
* @param x
 
* @param key
 
* @return
 
*/

public Value get(BinaryNode x,Key key){
   
//如果x空,直接返回空
   
if (x == null){
       
return null;
   
}
   
if (key.compareTo((Key) x.key) < 0){
       
return get(x.left,key);
   
}
   
//key > root.key
   
if (key.compareTo((Key) x.key) > 0){
       
return get(x.right,key);
   
}

   
if (key.compareTo((Key) x.key) == 0){
       
return (Value) x.value;
   
}
   
return null;
}

 

 

  • 当key=10删除时,需要找一个元素能够替代key=10
  • 这个元素要满足,左子树都小于该结点元素、右子树都大于该结点元素,所以需要在key=10的右子树选择一个最小的元素
  • 找到最小的元素后,删除该结点,并将最小结点元素指向要删除的key的左子树和右子树

 

/**
 *
删除指定二叉树的元素
 
* @param x
 
* @param key
 
* @return
 
*/

public BinaryNode delete (BinaryNode x,Key key){
   
//如果x为空
   
if (x == null){
       
return null;
   
}
   
//key < root.key
   
if (key.compareTo((Key) x.key) < 0){
        x.
left = delete(x.left,key);
   
}
   
//key > root.key
   
if (key.compareTo((Key) x.key) > 0){
        x.
right = delete(x.right,key);
   
}
   
//key = root.key
   
if (key.compareTo((Key) x.key) == 0){
       
//1.找到右子树中最小的结点
       
//1.1 如果右子树为空
       
if(x.right == null){
           
return x.left;
       
}
       
//1.2 左子树为空
       
if (x.left == null){
           
return x.right;
       
}
       
//1.3 左右子树都不为空:找到最小的结点并删除
       
BinaryNode minNode = x.right;
        while
(minNode.left != null){
            minNode = minNode.
left;
       
}
       
//2.找到最小结点的上一个节点并删除最小节点
       
BinaryNode node =  x.right;
        while
(node.left != null){
           
if(node.left.left == null)
                node.
left = null;
            else
               
node = node.left;
       
}
       
//x结点的左子树成为minnode的左子树
       
minNode.left = x.left;
       
//x结点的右子树成为minnode的右子树
       
minNode.right = x.right;
       
//x的父结点指向minnode
        
x = minNode;
   
}
   
length --;
    return
x;
}

  •  

 

4.测试代码

 

public static void testBinaryTree(){
    BinaryTree<Integer
,String> tree = new BinaryTree<>();
   
tree.delete(2);
   
System.out.println("空树删除:" + tree.size());
   
tree.put(1,"Tracy");
   
tree.put(2,"Kobe");
   
tree.put(3,"James");
   
System.out.println("现有的元素的个数:" + tree.size());
   
String first = tree.get(3);
   
System.out.println("第一个元素为:" + first);
   
tree.delete(2);
   
System.out.println("删除后的元素的个数:" + tree.size());
}

 

  • 二叉树查找最小键【P87】

 

public Key getMinKey(){
   
return (Key) getMinKey(root).key;
}
public BinaryNode getMinKey(BinaryNode x){
   
if (x == null)
       
return null;
    if
(x.left != null){
       
return getMinKey(x.left);
   
}
   
return x;
}

 

  • 二叉树查找最大键【P88】

 

public Key getMaxKey(){
   
return (Key) getMaxKey(root).key;
}
public BinaryNode getMaxKey(BinaryNode x){
   
if (x == null)
       
return null;
    if
(x.right != null){
       
return getMaxKey(x.right);
   
}
   
return x;
}

 

  • 二叉树遍历【P89-93】

 

  1. 前序(根→左→右)

FCADBEHGM

 

/**
 *
二叉树的前序遍历
 
* @return
 
*/

public void preErgodic(BinaryNode x,Queue<Key> keys){
   
//1.点是否空,空直接返回null
   
if(x == null){
       
return;
   
}
    keys.enqueue((
Key) x.key);
   
//2.如果左子空,则递归调用前序遍
   
if(x.left != null){
        preErgodic(x.
left,keys);
   
}
   
//3.如果右子空,则递归调用前序遍
   
if(x.right != null){
        preErgodic(x.
right,keys);
   
}
}

 

测试:

 

public static void testPreErgodic() throws InterruptedException {
    BinaryTree<String
,String> tree = new BinaryTree<>();
   
tree.put("E","5");
   
tree.put("B","2");
   
tree.put("G","7");
   
tree.put("A","1");
   
tree.put("D","4");
   
tree.put("F","6");
   
tree.put("H","8");
   
tree.put("C","3");
   
Queue<String> result = tree.preErgodic();
    for
(int i=0;i<tree.size();i++){
        System.
out.println(tree.get(result.dequeue()));
   
}
}

 

 

  1. 中序(左→根→右)使用较多,可以排序

ACBDFHEMG

 

/**
 *
二叉树的中序遍历
 
* @return
 
*/

public Queue<Key> midErgodic(){
    Queue<
Key> keys = new Queue<Key>();
    this
.midErgodic(root,keys);
    return
keys;
}

/**
 *
二叉树的中序遍历
 
* @return
 
*/

public void midErgodic(BinaryNode x,Queue<Key> keys){
   
//1.点是否空,空直接返回null
   
if(x == null){
       
return;
   
}
   
//2.递归,把根点的所有左子存入keys
   
if(x.left != null){
        midErgodic(x.
left,keys);
   
}
   
//3.存入根
   
keys.enqueue((Key) x.key);
   
//4.递归存入所有右子
   
if(x.right != null){
        midErgodic(x.
right,keys);
   
}
}

 

测试:

 

  1. 后序(左→右→根)

ABDCHMGEF

代码类似,自己完成。

 

  1. 层次遍历

 

 

  • 二叉树最大深度问题【P94】

主要思想:

计算左子树的最大深度M1,右子树最大深度M2,比较M1 与M2,取较大值+1(根节点)

即为最大深度。

 

  • 二叉树折纸问题【P95】

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值