// $Id: WeightedDiscretePDF.h,v 1.4 2006/07/07 05:54:31 zr Exp $ template class WDPDF_Node { private: bool m_mark; public: WDPDF_Node *parent, *left, *right; T key; float weight, sumWeights; public: WDPDF_Node(T key_, float weight_, WDPDF_Node *parent_); ~WDPDF_Node(); WDPDF_Node *sibling() { return this==parent->left?parent->right:parent->left; } void markRed() { m_mark = true; } void markBlack() { m_mark = false; } bool isRed() { return m_mark; } bool isBlack() { return !m_mark; } bool leftIsBlack() { return !left || left->isBlack(); } bool rightIsBlack() { return !right || right->isBlack(); } bool leftIsRed() { return !leftIsBlack(); } bool rightIsRed() { return !rightIsBlack(); } void setSum() { sumWeights = weight + (left?left->sumWeights:0) + (right?right->sumWeights:0); } }; template class WeightedDiscretePDF { private: WDPDF_Node *m_root; public: WeightedDiscretePDF(); ~WeightedDiscretePDF(); void insert(T item, float weight); void update(T item, float newWeight); void remove(T item); bool inTree(T item); /* pick a tree element according to its * weight. p should be in [0,1). */ T choose(float p); private: WDPDF_Node **lookup(T item, WDPDF_Node **parent_out); void split(WDPDF_Node *node); void rotate(WDPDF_Node *node); void lengthen(WDPDF_Node *node); void propogateSumsUp(WDPDF_Node *n); };