selectだけで実現できるLOUDS
ふと思い立って、LOUDSってビット列上の位置は不要で子ノードのIDだけわかればいいのでは、という気がした。この場合LOUDSの各種操作はselect()だけで良くなりrank()を使わなくなる。通常、簡潔ビットベクトルではselect()のほうが遅いのであまり効果は無いかもしれないが、それでも少しでも速いほうがいいはず。ってことで試してみた。
というわけでコードを置いておく。要望があればあとで解説を書く。
拙作のshellinfordライブラリの簡潔ビットベクトルを使ったが、他のライブラリでも同じように実装できるはず。
shellinford - shellinford: succinct document retrieval library - Google Project Hosting
#include <iostream> #include "shellinford_bit_vector.h" using namespace std; using namespace shellinford; // 親ノードIDを得る uint64_t parent(const bit_vector &bv, uint64_t id) { if (id == 0) { return bv.size(true); } uint64_t s = bv.select(id, false); uint64_t n = s - id; return n; } // i番目の子ノードIDを得る uint64_t ith_child(const bit_vector &bv, uint64_t id, uint64_t i) { uint64_t s = 0; if (id > 0) { s = bv.select(id - 1, true); } uint64_t n = s - id + i + 1; if (bv.get(s + 1)) { n = 0; } return n; } // 子ノード数を得る uint64_t degree(const bit_vector &bv, uint64_t id) { uint64_t d = bv.select(id, true) - 1; if (id > 0) { d -= bv.select(id - 1, true); } return d; } int main() { try { // 以下の木をLOUDSで表現する cout << "0 => {1}" << endl; cout << "1 => {2, 3, 4}" << endl; cout << "2 => {5, 6}" << endl; cout << "4 => {7}" << endl; // 各ノードの子ノード数をLevel-Orderで並べたもの vector<uint64_t> tree; tree.push_back(1); tree.push_back(3); tree.push_back(2); tree.push_back(0); tree.push_back(1); tree.push_back(0); tree.push_back(0); tree.push_back(0); // Jacobson's LOUDS uint64_t cur = 0; bit_vector louds; vector<uint64_t>::iterator it; for (it = tree.begin(); it != tree.end(); it++) { cur += (*it + 1); louds.set(cur); } louds.build(); // 各種操作をテスト。いずれもselect()を定数回呼ぶだけでOK。 for (uint64_t i = 0; i < tree.size(); i++) { cout << "parent(" << i << ") = " << parent(louds, i) << "\t"; cout << "1st child(" << i << ") = " << ith_child(louds, i, 0) << "\t"; cout << "degree(" << i << ") = " << degree(louds, i) << endl; } } catch (const char *err) { cerr << "ERR: " << err << endl; return 1; } return 0; }
これをlouds.ccとして保存。実行結果は以下のとおり。
$$ g++ louds.cc -lshellinford $$ ./a.out 0 => {1} 1 => {2, 3, 4} 2 => {5, 6} 4 => {7} parent(0) = 8 1st child(0) = 1 degree(0) = 1 parent(1) = 0 1st child(1) = 2 degree(1) = 3 parent(2) = 1 1st child(2) = 5 degree(2) = 2 parent(3) = 1 1st child(3) = 0 degree(3) = 0 parent(4) = 1 1st child(4) = 7 degree(4) = 1 parent(5) = 2 1st child(5) = 0 degree(5) = 0 parent(6) = 2 1st child(6) = 0 degree(6) = 0 parent(7) = 4 1st child(7) = 0 degree(7) = 0