本项目是一个homework,题目要求如下:
请设计一个Outlook日历,功能包括:
- 设定“忙碌”时间区间
[L, R](闭区间),表示在这个时间段内不可打扰。任意两个“忙碌”时间区间不相交。- 查询某时间区间是否是可用。给定查询
[L, R](闭区间),判断该时间区间是否“忙碌”。- 删除“忙碌”区间。给定查询
[L, R](闭区间),如果该区间为忙碌,或者该区间与忙碌区间相交,则删除所有与该区间冲突的忙碌区间。最后返回所有被删除的忙碌区间。
根据题意可以知道,两个区间只有三种关系,小于、大于和相交,所以可以把区间抽象成数字,则对应的数字也只有小于、大于、相等三种关系。又因为任意两个区间不相交,并且涉及到插入、删除、和查找三种操作,所以为了减少三种操作的时间复杂度,可以选择查找二叉树作为存储区间的数据结构。又平衡二叉查找树插入删除的时候树的调整步骤可能会很多,所以可以采用红黑树进行存储,又java中的treeMap就是采用的红黑树实现,所以本项目采用treeMap进行区间数据的存储。
- 插入: 插入时需要先判断树中是否有冲突的区间,O(logn),如果没有冲突,插入,O(logn),所以一共时间复杂度为 O(logn)
- 查询区间是否可用: 从头判断树中是否有相交的区间,O(logn)
- 删除区间: 删除区间的时候是从头判断树中是否有相交的区间,如果有则删除该区间,然后接着判断是否有相交区间,最好情况下是一遍结束,O(logn),最坏情况下则是把所有节点都删除掉,O(logn!)。
提供接口的类为MyCalender类,主要是进行请求数据的校验和返回统一的数据,具体的处理逻辑在MyMap类中实现。 运行测试需要先导入junit-4.7.jar包
题目要求的是闭区间,所以[5,10]和[10,15]严格上来说是相交的,但是考虑到实际生活中的日历需要,如果在5点到10点是忙碌的,不会认为自己10点到15点也是忙碌的,所以设计中将这种情况设计成了不相交。
个人理解这个日历应该是一个单机版的,不是在线的,所以本项目中将TreeMap通过文件的形式存储到了项目根目录下。不过这样就带来一个问题,存储TreeMap到文件中的时间应该远超于插入、删除内存中的区间的时间。可以通过定时将内存中数据写入到文件中进行缓解,但是这样又会带来数据不一致的隐患,这个问题现在还没有解决。 如果该日历是在线版的话,直接用数据库存储区间数据就可以了。
在数据量不大时树的高度不会太大,所以用红黑树效率是不错的,考虑到日历是单机版的话数据量应该不会太大,所以本项目采用了红黑树实现。如果数据量很大的话可以考虑采用B+树实现。也可以将现在的红黑树根据天数不同进行拆分,采用hashMap + treeMap的形式实现。
