【ADT】有序集合TreeSet

前言

Javascript中没有TreeSet这种数据结构,我参考Java中的API用 数组+二分 实现了一个类似功能的数据结构,但事实上,Java中的TreeSet是基于红黑树构建的,因此,二者在性能上并不能相提并论。

正如有些开源库会在开头标注一句:

Note that this project is meant to be used for learning and researching purposes only, and it is not meant to be used for production.

ADT

TreeSet:

	-methods
	size(): 	Number 		返回有序集合的大小
	pop():		Element 	弹出末尾元素
	shift(): 	Element 	弹出头部元素
	add(e):					将e插入有序集合,并使得有序集合依旧有序
	remove(e): 				将e从有序集合中删除
	has(e):		Boolean		判断有序集合中是否存在e
	get(i):		Element		取到排第i+1位的元素
	lower(e):	Element		查找最大的严格小于e的元素
	hihger(e):	Element		查找最小的大于等于e的元素
	_binarySearch(e):Number	返回值为正数表明有序数组中有该元素;负数表示可插入位置的相反数
	
	-props
	arr:	Array	内部数据结构为对象数组(有序数组)
	comparator: Function	自定义排序规则函数(默认规则为Number类型升序排序)
	

实现

class TreeSet {
    constructor(comparator) {
        this.arr = [];
        if(comparator) this.comparator = comparator;
        else this.comparator = (a,b) => a-b;
    }

    size() {
        return this.arr.length;
    }

    pop() {
        if(this.arr.length <= 0) throw new Error("can not pop() an element from an empty TreeSet!");
        return this.arr.splice(this.arr.length-1, 1);
    }

    shift() {
        if(this.arr.length <= 0) throw new Error("can not shift() an element from an empty TreeSet!");
        return this.arr.splice(0, 1);
    }

    add(e) {
        let idx = this._binarySearch(e);
        if(idx < 0) {
            idx = -idx-1;
            this.arr.splice(idx, 0, e);
        } 
    }

    remove(e) {
        let idx = this._binarySearch(e);
        if(idx >= 0) this.arr.splice(idx, 1);
        else return -1;
    }

    get(i) {
        return this.arr[i];
    }

    has(e) {
        return this._binarySearch(e) >= 0;
    }

    lower(e) {
        let idx = this._binarySearch(e);
        if(idx < 0) return this.arr[-idx-2];
        else return this.arr[idx-1];
    }

    higher(e) {
        let idx = this._binarySearch(e);
        if(idx < 0) return this.arr[-idx-1];
        else return this.arr[idx];
    }

    _binarySearch(e) {
        let low = 0;
        let high = this.arr.length-1;

        while(low <= high) {
            let mid = (low + high) >>> 1;
            let val = this.arr[mid];
            let cmp = this.comparator(val, e);
            if(cmp < 0) low = mid+1;
            else if(cmp > 0) high = mid-1;
            else return mid;
        }

        return -(low+1);
    }
}

测试用例

在这里插入图片描述
测试用例还要补充:

lower(9): 预期8
higher(9): 预期11

lower(11): 预期8
higher(11):预期11

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值