《數據結構》學習筆記4——補充
/* .. 離開了鄧公的視頻講解,只能自己看課件瞎捉摸了,僅以此立下flag,摸摸前行的墊腳石。 ..*/
【第八章 高級搜索樹】
1-Dimensional Range Query:Counting & Reporting
對於一位向量,大量隨機查詢,Brute-force 是O(n),考慮排序+二分查找?
1d-tree (Lowest Common Ancestor):排序時間O(nlogn),空間O(n)
plannar Range Query:2d-tree kd-tree (查閱相關博客)
quadtree 四分樹
Multi-Level Search Tree: x-Query + y-Query –》 x-Query * y-Query (BBST<BBST<T>> -- BBST<Vector<T>>)
range tree : an MLST with fractional cascading
interval tree : 存儲interval元素,查詢點在的interval
segment tree 線段樹:用於區間求和(最值),建樹,修改,查詢。
參考 https://www.cnblogs.com/wuyudong/p/segment-tree.html
https://www.cnblogs.com/xiaoyao24256/p/6590885.html
#define N 1000
struct node {
int l, r, value;
int add;
} tree[N*4];
void build(int l, int r, int v) {
tree[v].l = l; tree[v].r = r;
if (l == r) { tree[v].value = v; return; }
int mid = (l + r) >> 1;
build(v * 2, l, mid);
build(v * 2 + 1, mid + 1, r);
tree[v].value = tree[v * 2].value + tree[v * 2 + 1].value; // 區間求和
}
void update(int v, int r, int l, int m) { // 區間[l, r), 增量m
if (tree[v].l == l && tree[v].r == r) {
tree[v].value += m * (r - l + 1);
tree[v].add = m;
return;
}
if (tree[v].add) {
tree[v * 2].add += tree[v].add;
tree[v * 2 + 1].add += tree[v].add;
tree[v].add = 0;
}
int mid = (tree[v].l + tree[v].r) >> 1;
if (r <= mid) {
update(v * 2, l, r, m);
}
else {
if (l > mid) {
update(v * 2 + 1, l, r, m);
}
else {
update(v * 2, l, mid, m);
update(v * 2 + 1, mid + 1, r, m);
}
}
}
【第九章 詞典】
跳表 skip lists :[William Pugh, 1989] a probabilistic alternative to balanced trees
性能和平衡樹差不多。生長概率逐層減半,空間期望值O(n),橫向和縱向查找期望值均為O(logn)
通過多層有序鏈表實現:主要三個函數,查找;插入(用隨機函數確定是否生長);刪除。(以下代碼僅代表思路)
1 template <typename T> class Quadlist { 2 private: int _size; QuadlistNodePosi(T) header, trailer;跳表3 protected: void init(); int clear(); // 初始化、清除所有節點 4 public: QuadlistNodePosi(T) first() const { return header->succ; } 5 QuadlistNodePosi(T) last() const { return trailer->pred; } 6 T remove(QuadlistNodePosi(T) p); // 刪除 7 QuadlistNodePosi(T) insertAfterAbove( // 插入e,成為p後繼和b上鄰 8 T const & e, 9 QuadlistNodePosi(T) p, 10 QuadlistNodePosi(T) b = NULL); 11 }; 12 13 template <typename K, typename V> class Skiplist : 14 public Dictionary<K, V>, public List<Quadlist<Entry<K, V>> * > { 15 protected: 16 bool skipSearch(ListNode< Quadlist<Entry<K, V>>*>* &qlist, 17 QuadlistNode<Entry<K, V>>* &p, K &k); 18 public: 19 int size() { return empty() ? 0 : last()->data->size(); } 20 int level() { return List::size(); } 21 bool put(K, V); 22 V* get(K); 23 bool remove(K); 24 }; 25 26 bool skipSearch(&qlist, &p, &k) { 27 /* 從指定層qlist的首節點p出發,向右succ 向下below 查找k, 28 在每一層向後查找,直到出現key,或者溢出至trailer。 29 命中,則成功返回 30 否則進入下一層qlist,若已穿透底層,則意味著失敗 31 p進入當前塔的下一節點 32 確認:無論成功或失敗,返回的p均為其中不大於e的最大者?體會哨兵的作用*/ 33 while (true) { 34 while (p->succ && (p->entry.key <= k)) p = p->succ; p = p->pred; 35 if (p->pred && (k == p->entry.key)) return true; 36 qlist = qlist->succ; 37 if (!qlist->succ) return false; 38 p = p->pred ? p->below : qlist->data->first(); 39 } 40 } 41 42 bool put(k, v) { 43 Entry<K, V> e = Entry<K, V>(k, v); 44 if (empty()) insertAsFirst(new Quadlist<Entry<K, V>>); 45 ListNode<Quadlist<Entry<K, V>>*>* qlist = first(); 46 QuadlistNode<Entry<K, V>>* p = qlist->data->first(); 47 if (skipSerach(qlist, p, k)) 48 while (p->below) p = p->below; // 強制轉到塔底 49 /* 以下,緊鄰與p的右側,以新節點b為基座,自底而上逐層長出一座新塔 */ 50 qlist = last(); 51 QuadlistNode<Entry<K, V>>* b = qlist->data->insertAfterAbove(e, p); 52 while (rand() & 1) { 53 /* 隨機確定塔是否長高, 54 先定位不低於此高度的最近前驅p, 55 若已經最高,則創建新層;若是header,則轉移p至上一層header;否則,直接提升p 56 qlist提升一層 57 插入節點至 p之後,b之上 */ 58 while (qlist->data->valid(p) && !p->above) p = p->pred; 59 if (!qlist->data->valid(p)) { 60 if (qlist == first()) 61 insertAsFirst(new Quadlist<Entry<K, V>>); 62 p = qlist->pred->data->first()->pred; 63 } 64 else p = p->above; 65 qlist = qlist->pred; 66 b = qlist->data->insertAsAbove(e, p, b); 67 } 68 } 69 70 bool remove(k) { 71 /* 表為空或者不存在,則返回 72 先記住下一層節點,然後刪除當前節點,轉到下一層繼續刪除。 73 需要清除已可能不含詞條的頂層。 */ 74 if (empty()) return false; 75 ListNode<>* qlist = first(); 76 QuadlistNode<>* p = qlist->data->first(); 77 if (!skipSearch(qlist, p, k)) return false; 78 do { 79 QuadlistNode<>* lower = p->below; 80 qlist->data->remove(p); 81 p = lower; qlist = qlist->succ; 82 } while (qlist->succ); 83 while (!empty() && first()->data->empty()) 84 List::remove(first()); 85 return true; 86 }
位圖 bitmap
依散列思想,所有離散集或顯示或隱式可表達為整數集。
使用物理地址連續的一段空間,各元素依次對應於一個bit位
應用:小集合+大數據,內存要求高,否則將導致整體I/O效率低下;素數篩法;
1 class Bitmap { 2 private: 3 char* M; // 以char(8 bit)為單位的bitmap 4 int N; // 位圖長度 以sizeof(char)為單位 5 public: 6 Bitmap(int n = 8) { M = new char[N = (n + 7) / 8]; memset(M, 0, N); } 7 ~Bitmap() { delete[] M; M = NULL; } 8 void set(int k); void clear(int k); bool test(int k); 9 }; 10 void set(int k) { 11 expand(k); 12 M[k >> 3] |= (0x80 >> (k & 0x07)); // ‘1000 0000‘ 右移 k%8 的位數 13 } 14 void clear(int k) { // 體會一下位操作,移位後取非再並;因為要覆蓋,就必須用並 15 expand(k); 16 M[k >> 3] &= ~(0x80 >> (k & 0x07)); 17 } 18 void test(int k) { 19 expand(k); 20 return M[k >> 3] & (0x80 >> (k & 0x07)); 21 } 22 void expand(int k) { 23 if (k < 8 * N) return; 24 int oldN = N; char* oldM = M; 25 M = new char[N = (2 * k + 7) / 8]; // 加倍擴容策略 26 memcpy_s(M, N, oldM, oldN); 27 delete[] oldM; 28 }bitmap
初始化操作對算法整體的影響——很深遠:用校驗環進行初始化 O(1),[J.Hopcroft, 1974]
新增兩個向量 和一個標識
1 int F[m]; // From 2 int T[m]; int top = 0; // To 及其棧頂標識 3 bool Bitmap::test(int k) { // O(1) 4 return (0 <= F[k]) && (F[k] < top) 5 && (k == T[F[k]]); // 校驗環 6 } 7 bool Bitmap::reset() { top = 0; } // 復位,切斷所有校驗環, O(1)!!! 8 bool Bitmap::set(int k) { 9 if (!test(k)) { 10 T[top] = k; F[k] = top++; // 創建校驗環 11 } 12 } 13 bool Bitmap::clear(int k) { 14 if (test(k)) 15 if (--top) { 16 F[T[top]] = F[k]; T[F[k]] = T[top]; // 用top位置的環覆蓋 17 } 18 }校驗環
MD5算法
【第十一章 串】
鍵樹、 Trie樹(retrieve)、字典樹:多模式匹配,(KMP算法是單模式匹配)
算法思想:空間換時間,利用字符串的公共前綴來降低查詢時間的開銷以達到提高效率的目的。
一種哈希樹的變種。典型應用是用於統計和排序大量的字符串(但不僅限於字符串),所以經常被搜索引擎系統用於文本詞頻統計。【下圖感受一下】
網上參考:https://blog.csdn.net/hackbuteer1/article/details/7964147
《數據結構》學習筆記4——補充