二叉搜索树rank与select的实现

来源:1-15 更多二分搜索树相关话题

宇宇子

2021-08-10 16:32:05

问题描述:

波波老师您好,这里我是使用中序遍历加入链表,然后实现的rank和select方法,老师这里有没有更好的方法实现呢?

相关代码:

//查找二叉树中某一个节点是排名第几的元素
public int rank(E e) {
LinkedList<E> list = new LinkedList<>();
rank(root, e, list);
int num = 0;
for (int i = 0; i < list.size(); i++) {
num++;
if (list.get(i).equals(e)) {
return num;
}
}
//没有找到返回-1
return -1;
}

//递归实现rank方法,使用中序遍历思路
private void rank(Node node, E e, LinkedList<E> list) {
if (node == null) {
//没有找到该元素
return;
}
rank(node.left, e, list);
list.add(node.e);
rank(node.right, e, list);
}

//输入从小到大的排名,输出该节点的值
public E select(int rankNum) {
//判断输入的序号是否合法
if (rankNum <= 0 || rankNum > size) {
throw new IllegalArgumentException("Error rankNumber");
}
LinkedList<E> list = new LinkedList<>();
select(root, list);
return list.get(rankNum - 1);
}

//将二叉树从小到大加入链表中
private void select(Node node, LinkedList<E> list) {
if (node == null) {
return;
}
select(node.left, list);
list.add(node.e);
select(node.right, list);
}


写回答

2回答

宇宇子

提问者

2021-08-10

对了老师,我这里已经实现了恢复size的二叉树,但是没有明白知道节点有多少子节点与获得节点的排名之间的关系

​public class SizeBinarySearchTree<E extends Comparable<E>> {
/*
在node中维护size
*/
private class Node {
public E e;
public Node left, right;
public int size;//记录每一个节点下有多少子节点

public Node(E e) {
this.e = e;
left = right = null;
size = 1;
}
}
//成员变量一个就够了,不需要再维护一个size变量
private Node root;

public void add(E e) {
root = add(root, e);
}

private Node add(Node node, E e) {
if (node == null) {
return new Node(e);
}
//所有递归过的节点都会size+1
node.size++;

if (e.compareTo(node.e) < 0) {
node.left = add(node.left, e);
} else if (e.compareTo(node.e) > 0) {
node.right = add(node.right, e);
}
return node;
}

//中序遍历验证是否维护成功
public void inOrder() {
inOrder(root);
}

private void inOrder(Node node) {
if (node == null) {
return;
}
inOrder(node.left);
System.out.println("size=" + node.size + ",value=" + node.e);
inOrder(node.right);
}

// public static void main(String[] args) {
// SizeBinarySearchTree<Integer> sbs = new SizeBinarySearchTree<>();
// int[] nums = {28, 16, 30, 13, 22, 29, 42};
// for (int n : nums) {
// sbs.add(n);
// }
// sbs.inOrder();
// }
}


1

liuyubobobo

2021-08-10

关于 bst 上 rank 和 select 的实现,可以参考这里:https://git.imooc.com/class-105/Play-Algorithms-and-Data-Structures/src/master/15-Binary-Search-Tree/Optional-02-Rank-and-Select/src/BST.java


(333 行开始)


​node 中的 sz 存储的是以这个 node 为根节点的子树一共有多少个节点。请根据这个定义,仔细理解一下这个代码中 sz 和 index 的关系是怎样的。如果有疑问可以再做提问。


另外,请理解一下我是如何测试 rank 和 select 的。这个课程给出了很多测试方式。虽然这个课程不是专门系统地讲解测试的,但是其中的很多测试方式是值得借鉴的,有助于大家进一步学习专门的单元测试的。很多时候,对于程序的逻辑,试图通过看的方式来检验程序逻辑是不靠谱的,必须做相应的基本测试。


继续加油!:)

0

算法与数据结构

波波老师5年集大成之作,算法与数据结构系统学习,考试、面试、竞赛通用

2614 学习 · 1087 问题

查看课程