📄 avltree.h
字号:
/* * Copyright (C) 2008 Apple Inc. All rights reserved. * * Based on Abstract AVL Tree Template v1.5 by Walt Karas * <http://geocities.com/wkaras/gen_cpp/avl_tree.html>. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#ifndef AVL_TREE_H_#define AVL_TREE_H_#include "Assertions.h"namespace WTF {// Here is the reference class for BSet.//// class BSet// {// public://// class ANY_bitref// {// public:// operator bool ();// void operator = (bool b);// };//// // Does not have to initialize bits.// BSet();//// // Must return a valid value for index when 0 <= index < maxDepth// ANY_bitref operator [] (unsigned index);//// // Set all bits to 1.// void set();//// // Set all bits to 0.// void reset();// };template<unsigned maxDepth>class AVLTreeDefaultBSet {public: bool& operator[](unsigned i) { ASSERT(i < maxDepth); return m_data[i]; } void set() { for (unsigned i = 0; i < maxDepth; ++i) m_data[i] = true; } void reset() { for (unsigned i = 0; i < maxDepth; ++i) m_data[i] = false; }private: bool m_data[maxDepth];};// How to determine maxDepth:// d Minimum number of nodes// 2 2// 3 4// 4 7// 5 12// 6 20// 7 33// 8 54// 9 88// 10 143// 11 232// 12 376// 13 609// 14 986// 15 1,596// 16 2,583// 17 4,180// 18 6,764// 19 10,945// 20 17,710// 21 28,656// 22 46,367// 23 75,024// 24 121,392// 25 196,417// 26 317,810// 27 514,228// 28 832,039// 29 1,346,268// 30 2,178,308// 31 3,524,577// 32 5,702,886// 33 9,227,464// 34 14,930,351// 35 24,157,816// 36 39,088,168// 37 63,245,985// 38 102,334,154// 39 165,580,140// 40 267,914,295// 41 433,494,436// 42 701,408,732// 43 1,134,903,169// 44 1,836,311,902// 45 2,971,215,072//// E.g., if, in a particular instantiation, the maximum number of nodes in a tree instance is 1,000,000, the maximum depth should be 28.// You pick 28 because MN(28) is 832,039, which is less than or equal to 1,000,000, and MN(29) is 1,346,268, which is strictly greater than 1,000,000.template <class Abstractor, unsigned maxDepth = 32, class BSet = AVLTreeDefaultBSet<maxDepth> >class AVLTree {public: typedef typename Abstractor::key key; typedef typename Abstractor::handle handle; typedef typename Abstractor::size size; enum SearchType { EQUAL = 1, LESS = 2, GREATER = 4, LESS_EQUAL = EQUAL | LESS, GREATER_EQUAL = EQUAL | GREATER }; Abstractor& abstractor() { return abs; } inline handle insert(handle h); inline handle search(key k, SearchType st = EQUAL); inline handle search_least(); inline handle search_greatest(); inline handle remove(key k); inline handle subst(handle new_node); void purge() { abs.root = null(); } bool is_empty() { return abs.root == null(); } AVLTree() { abs.root = null(); } class Iterator { public: // Initialize depth to invalid value, to indicate iterator is // invalid. (Depth is zero-base.) Iterator() { depth = ~0U; } void start_iter(AVLTree &tree, key k, SearchType st = EQUAL) { // Mask of high bit in an int. const int MASK_HIGH_BIT = (int) ~ ((~ (unsigned) 0) >> 1); // Save the tree that we're going to iterate through in a // member variable. tree_ = &tree; int cmp, target_cmp; handle h = tree_->abs.root; unsigned d = 0; depth = ~0U; if (h == null()) // Tree is empty. return; if (st & LESS) // Key can be greater than key of starting node. target_cmp = 1; else if (st & GREATER) // Key can be less than key of starting node. target_cmp = -1; else // Key must be same as key of starting node. target_cmp = 0; for (;;) { cmp = cmp_k_n(k, h); if (cmp == 0) { if (st & EQUAL) { // Equal node was sought and found as starting node. depth = d; break; } cmp = -target_cmp; } else if (target_cmp != 0) { if (!((cmp ^ target_cmp) & MASK_HIGH_BIT)) { // cmp and target_cmp are both negative or both positive. depth = d; } } h = cmp < 0 ? get_lt(h) : get_gt(h); if (h == null()) break; branch[d] = cmp > 0; path_h[d++] = h; } } void start_iter_least(AVLTree &tree) { tree_ = &tree; handle h = tree_->abs.root; depth = ~0U; branch.reset(); while (h != null()) { if (depth != ~0U) path_h[depth] = h; depth++; h = get_lt(h); } } void start_iter_greatest(AVLTree &tree) { tree_ = &tree; handle h = tree_->abs.root; depth = ~0U; branch.set(); while (h != null()) { if (depth != ~0U) path_h[depth] = h; depth++; h = get_gt(h); } } handle operator*() { if (depth == ~0U) return null(); return depth == 0 ? tree_->abs.root : path_h[depth - 1]; } void operator++() { if (depth != ~0U) { handle h = get_gt(**this); if (h == null()) { do { if (depth == 0) { depth = ~0U; break; } depth--; } while (branch[depth]); } else { branch[depth] = true; path_h[depth++] = h; for (;;) { h = get_lt(h); if (h == null()) break; branch[depth] = false; path_h[depth++] = h; } } } } void operator--() { if (depth != ~0U) { handle h = get_lt(**this); if (h == null()) do { if (depth == 0) { depth = ~0U; break; } depth--; } while (!branch[depth]); else { branch[depth] = false; path_h[depth++] = h; for (;;) { h = get_gt(h); if (h == null()) break; branch[depth] = true; path_h[depth++] = h; } } } } void operator++(int) { ++(*this); } void operator--(int) { --(*this); } protected: // Tree being iterated over. AVLTree *tree_; // Records a path into the tree. If branch[n] is true, indicates // take greater branch from the nth node in the path, otherwise // take the less branch. branch[0] gives branch from root, and // so on. BSet branch; // Zero-based depth of path into tree. unsigned depth; // Handles of nodes in path from root to current node (returned by *). handle path_h[maxDepth - 1]; int cmp_k_n(key k, handle h) { return tree_->abs.compare_key_node(k, h); } int cmp_n_n(handle h1, handle h2) { return tree_->abs.compare_node_node(h1, h2); } handle get_lt(handle h) { return tree_->abs.get_less(h); } handle get_gt(handle h) { return tree_->abs.get_greater(h); } handle null() { return tree_->abs.null(); } }; template<typename fwd_iter> bool build(fwd_iter p, size num_nodes) { if (num_nodes == 0) { abs.root = null(); return true; } // Gives path to subtree being built. If branch[N] is false, branch // less from the node at depth N, if true branch greater. BSet branch; // If rem[N] is true, then for the current subtree at depth N, it's // greater subtree has one more node than it's less subtree. BSet rem; // Depth of root node of current subtree. unsigned depth = 0; // Number of nodes in current subtree. size num_sub = num_nodes; // The algorithm relies on a stack of nodes whose less subtree has // been built, but whose right subtree has not yet been built. The // stack is implemented as linked list. The nodes are linked // together by having the "greater" handle of a node set to the // next node in the list. "less_parent" is the handle of the first // node in the list. handle less_parent = null(); // h is root of current subtree, child is one of its children. handle h, child; for (;;) { while (num_sub > 2) { // Subtract one for root of subtree. num_sub--; rem[depth] = !!(num_sub & 1); branch[depth++] = false; num_sub >>= 1; } if (num_sub == 2) { // Build a subtree with two nodes, slanting to greater. // I arbitrarily chose to always have the extra node in the // greater subtree when there is an odd number of nodes to // split between the two subtrees. h = *p; p++; child = *p; p++; set_lt(child, null()); set_gt(child, null()); set_bf(child, 0); set_gt(h, child); set_lt(h, null()); set_bf(h, 1); } else { // num_sub == 1 // Build a subtree with one node. h = *p; p++; set_lt(h, null()); set_gt(h, null()); set_bf(h, 0); } while (depth) { depth--; if (!branch[depth]) // We've completed a less subtree. break; // We've completed a greater subtree, so attach it to // its parent (that is less than it). We pop the parent // off the stack of less parents. child = h; h = less_parent; less_parent = get_gt(h); set_gt(h, child); // num_sub = 2 * (num_sub - rem[depth]) + rem[depth] + 1 num_sub <<= 1; num_sub += 1 - rem[depth]; if (num_sub & (num_sub - 1)) // num_sub is not a power of 2 set_bf(h, 0); else // num_sub is a power of 2 set_bf(h, 1); } if (num_sub == num_nodes) // We've completed the full tree. break; // The subtree we've completed is the less subtree of the // next node in the sequence. child = h; h = *p; p++; set_lt(h, child); // Put h into stack of less parents. set_gt(h, less_parent); less_parent = h; // Proceed to creating greater than subtree of h. branch[depth] = true; num_sub += rem[depth++]; } // end for (;;) abs.root = h; return true; }protected: friend class Iterator; // Create a class whose sole purpose is to take advantage of // the "empty member" optimization. struct abs_plus_root : public Abstractor { // The handle of the root element in the AVL tree. handle root; }; abs_plus_root abs; handle get_lt(handle h) { return abs.get_less(h); } void set_lt(handle h, handle lh) { abs.set_less(h, lh); } handle get_gt(handle h) { return abs.get_greater(h); } void set_gt(handle h, handle gh) { abs.set_greater(h, gh); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -