红魔咖啡馆

头发越掉越多,头发越掉越少

0%

【CS61B】Lec16-Extends, Sets, Maps, and BSTs

Lec16 - Extends, Sets, Maps, and BSTs

Extends

从前,若一个类是接口的下位词,我们使用implements来书写方法的实现

但若想实现一个类是另一个类的下位词,我们需要使用extends

extends可以用于类与类、接口与接口之间

例:实现RotatingSLList

即让最后一个元素右旋到第一个元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package Lec16;

public class RotatingSLList<Item> extends SLList<Item> {
    public void rotateRight(){
        Item x = removeLast();
        addFirst(x);
    }
    public static void main(String[] args){
        RotatingSLList<Integer> rsl = new RotatingSLList<>();
        rsl.addLast(10);
        rsl.addLast(11);
        rsl.addLast(12);
        rsl.addLast(13);

        rsl.rotateRight();
        rsl.print();
    }
}

extends继承了SLList中的所有成员:

  • 所有实例与静态变量
  • 所有方法(除了构造函数)
  • 所有嵌套类

但若成员是私有的就无法访问了

例:实现VengefulSLList

记录被删除的元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package Lec16;


import java.util.ArrayList;
import java.util.List;

public class VengefulSLList<Item> extends SLList<Item>{
    private SLList<Item> deletedItems ;
    public VengefulSLList(){
        deletedItems = new SLList<Item>();
    }

    @Override
    public Item removeLast(){
        Item removedItem = super.removeLast(); // 使用父类的方法
        deletedItems.addLast(removedItem);
        return removedItem;
    }
    public void printLostItems(){
        deletedItems.print();
    }
    public static void main(String[] args){
        VengefulSLList<Integer> vsl = new VengefulSLList<>();
        vsl.addLast(1);
        vsl.addLast(5);
        vsl.addLast(10);
        vsl.addLast(15);

        vsl.removeLast();
        vsl.removeLast();

        vsl.printLostItems();
    }
}

这里我们实现了对继承方法的重写

其中,我们可以使用super来调用父类中的方法

BST

随机表

链表的搜索效率较慢,我们可以在不同节点间随机额外添加一些链接,这样可以依赖随机性获得更好的效率

二叉搜索树的原理

若我们将每次搜索都折半,就能大幅提高效率,一个链表可以进行如下改造:

BST

这是一棵二叉搜索树

二叉搜索树是一个有根的二叉树,对于书中的每个节点

  • 左子树中的每个节点的值都小于该节点的值
  • 右子树中的每个节点的值都大于该节点的值
BST

寻找特定元素

  • 若待寻找元素等于当前元素,返回
  • 若待寻找元素小于当前元素,前往左子树寻找
  • 若待寻找元素大于当前元素,前往右子树寻找

时间复杂度:\(\Theta(\log n)\)

因此搜索一颗完全BST的速度是很快的

1
2
3
4
5
6
7
8
9
10
static BST find(BST T, key sk){
    if (T==null)
        return null;
    if (sk.equals(T.key))
        return T;
    else if (sk<T.key)
        return find(T.left, sk);
    else
        return find(T.right, sk);
}

添加元素

首先寻找待插入元素

  • 若找到了就不进行操作
  • 若没找到
    • 创建一个新节点
    • 创建合适链接

使用递归书写

1
2
3
4
5
6
7
8
9
static BST insert(BST T, key ik){
    if (T==null) 
        return new BST(ik);
    if (ik<T.key)
        T.left = insert(T.left, ik);
    else if (ik>T.key)
        T.right = insert(T.right, ik);
    return T;
}

删除元素

删除没有孩子的节点:

直接删除,即将其父节点对应的左/右节点置空

删除一个孩子的节点:

要在维持BST性质的前提下删除:可以发现该节点的孩子一定大于(右侧)或小于(左侧)该节点

故我们可以寻找该节点的孩子,将指向它的节点指向他的孩子即可

删除两个孩子的节点:

找到左子树最大的节点或右子树最小的节点,替代待删除节点即可