本文原创为freas_1990,转载请标明出处:http://blog.csdn.net/freas_1990/article/details/13360863
Lighty里采用了“自适应树”,而且是直接借用D. Sleator在1994年实现的代码。
其实,在关键的数据结构上借用历史证明了健壮性的代码比自己重复造轮子要实际得多——如果自己实现,谁能保证这个“新家伙”不会出问题呢?
同样的案例出现在redis里的LZF压缩,pqsort功能等等。
我们来欣赏一下最关键的一个函数——splay。
- /* Splay using the key i (which may or may not be in the tree.)
- * The starting root is t, and the tree used is defined by rat
- * size fields are maintained */
- splay_tree * splaytree_splay (splay_tree *t, int i) {
- splay_tree N, *l, *r, *y;
- int comp, l_size, r_size;
- if (t == NULL) return t;
- N.left = N.right = NULL;
- l = r = &N;
- l_size = r_size = 0;
- for (;;) {
- comp = compare(i, t->key);
- if (comp < 0) {
- if (t->left == NULL) break;
- if (compare(i, t->left->key) < 0) {
- y = t->left; /* rotate right */
- t->left = y->right;
- y->right = t;
- t->size = node_size(t->left) + node_size(t->right) + 1;
- t = y;
- if (t->left == NULL) break;
- }
- r->left = t; /* link right */
- r = t;
- t = t->left;
- r_size += 1+node_size(r->right);
- } else if (comp > 0) {
- if (t->right == NULL) break;
- if (compare(i, t->right->key) > 0) {
- y = t->right; /* rotate left */
- t->right = y->left;
- y->left = t;
- t->size = node_size(t->left) + node_size(t->right) + 1;
- t = y;
- if (t->right == NULL) break;
- }
- l->right = t; /* link left */
- l = t;
- t = t->right;
- l_size += 1+node_size(l->left);
- } else {
- break;
- }
- }
- l_size += node_size(t->left); /* Now l_size and r_size are the sizes of */
- r_size += node_size(t->right); /* the left and right trees we just built.*/
- t->size = l_size + r_size + 1;
- l->right = r->left = NULL;
- /* The following two loops correct the size fields of the right path */
- /* from the left child of the root and the right path from the left */
- /* child of the root. */
- for (y = N.right; y != NULL; y = y->right) {
- y->size = l_size;
- l_size -= 1+node_size(y->left);
- }
- for (y = N.left; y != NULL; y = y->left) {
- y->size = r_size;
- r_size -= 1+node_size(y->right);
- }
- l->right = t->left; /* assemble */
- r->left = t->right;
- t->left = N.right;
- t->right = N.left;
- return t;
- }
自适应树具备与生俱来的“Cache”功能,在处理冷、热分明的数据时,效果非常好。但是,如果数据本身很离散,无任何规律可言,那么,采用这种数据结构会适得其反。这个时候,更好的选择或许是“红黑树”。
今天就这样吧。早点休息了。
周一没有出去TB,在家休息,反而显得无聊了。