区间树
如何擴張數據結構
1) 選擇基礎數據結構
2) 確定要在基礎數據結構中記錄得附加信息
3) 提供基本(內部)操作來維護附加信息
4) 設計新得接口
?
?
1 是一顆紅黑樹
2 是以區間左端點維護的紅黑樹
3 額外信息是在每個節點中, 保存了以該節點為根的樹中的最右的區間端點
?
class Seg {int i, j;int upbound; public:int lower() const {return i;}int higher() const {return j;}int upper() const {return upbound;}bool interval(const Seg &r){if(i > r.j || j < r.i)return false;return true;} };interval-search(T, Seg &i) {x = root(T);while(x && !x.interval(i)){if(x.left && x.left.upper() >= i.lower())x = x.left;else x = x.right;}return x; }
?
個人說明:
1) 算法是正確的,可以正確返回與指定區間重疊的區間
2) 該算法只返回與i有重疊得一個區間, 并不是所有的區間
3) 該算法應該是非常容易錯的。 若把其中的語句修改一下, 算法就錯了。
修改之前 if(x.left && x.left.upper() >= i.lower())x = x.left; else x = x.right;修改之后為:/errorrrrrrrr if(x.right && x.right.upper() >= i.lower())x = x.right; elsex = x.left;舉例如下, 根節點區間為[20, 21, 40] //40為upper 左孩子區間為[10, 40, 40] 右孩子區間為[25, 40, 40] 查找的區間為 [12,13] 按照修改之后的算法流程, 則到右子樹中去查找了; 但這個[12,13]恰恰是只可能出現在左孩子樹中。
算法導論中文版pdf中有細微描述是有問題的
?
?
根本原因是該區間樹是以左端點遞增有序的方式構建的紅黑樹(二叉排序樹)。
?
?
?
interval_insert, interval_delete 待補充
?
?
interval_insert很簡單, 只需要注意更新upper就行
interval_insert(x, i) //i插入到以x為根的樹中 {while(1){if(i.higher() > x.upper()) //更新上界x.upbound = i.higher();if(i.lower() < x.lower()) //然后一直走到尾插入{if(x.left)x = x.left;else{x.left = i;return;}}else{if(x.right)x = x.right;else{x.right= i;return;}} }
?
?
interval_delete 需要回溯, 而且需要精確判斷兩個區間是否相同, 相同才能delete ?
?
// 找到x的前驅或者后繼替換x 【二叉樹的刪除操作】
// 只需要修改該路徑上的upper
使用棧是肯定可以解決的遞歸呢? interval_delete(T, p, x, i) //在以樹T中刪除i {if(x == i){delete(T, p, x, i);} else if(i < x){p = x;x = x.leftinterval_delete(T, p, x, i);}else {p = x;x = x.right;interval_delete(T, p, x, i);}//TODO修改p,x的upper }
?
總結
- 上一篇: B-树 的其他
- 下一篇: 得到不小于x的最小的2的幂