|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 andalousie 于 2014-4-27 15:33 编辑
感觉自己好久没在鱼C上发东西了,虽然总是签到。
今天发一个随机化二叉树吧,包含了中序遍历的迭代器。
和往常一样,直接上代码~
RandomizedBST.cpp#include <iostream>
#include <string>
#include "Random.h"
#include "stack.h"
template<typename Index, typename Value> class BSTIterator;
template<typename Index, typename Value>
class BST
{
protected:
struct Node
{
Node (Index k, Value v)
:key(k), val(v), left(0),
right(0), N(1)
{}
Index key; // key
Value val; // associated data
Node *left, *right; // left and right subtrees
int N; // size of subtree rooted at this node
};
public:
typedef BSTIterator<Index, Value> iterator;
friend class BSTIterator<Index, Value>;
BST(): root(0) {}
/*************************************************************************
* BST search
*************************************************************************/
bool contains(Index& key) {
return get(key) != 0;
}
// return value associated with the given key
// if no such value, return null
Value get(const Index& key) {
return get(root, key);
}
/*************************************************************************
* randomized insertion
*************************************************************************/
void put(Index key, Value val) {
root = putRoot(root, key, val);
}
// remove and return value associated with given interval;
// if no such interval exists return null
Value remove(Index key) {
Value value = get(key);
root = remove(root, key);
return value;
}
Index select(int k) { return select(root, k)->key; }
Index min()
{
Index key = 0;
for (Node * x = root; x; x = x->left)
key = x->key;
return key;
}
Index max()
{
Index key = 0;
for (Node * x = root; x; x = x->right)
key = x->key;
return key;
}
int size() { return size(root); }
int height() { return height(root); }
iterator begin() { return iterator(root); }
iterator end () { return iterator(0); }
private:
Node * root;
Random rnd;
int size(Node * x) {
if (!x) return 0;
else return x->N;
}
int height(Node * x) {
if (!x) return 0;
return 1 + (height(x->left) > height(x->right)
? height(x->left) : height(x->right));
}
//Private methods
Value get(Node *x, Index key)
{
if (!x) return 0;
int cmp = compare(key, x->key);
if (cmp < 0) return get(x->left, key);
else if (cmp > 0) return get(x->right, key);
else return x->val;
}
// make new node the root with uniform probability
Node * put(Node * x, Index key, Value val) {
if (!x) return new Node(key, val);
int cmp = compare(key, x->key);
if (!cmp)
{
x->val = val;
return x;
}
if (rnd.bernoulli(1.0 / (size(x) + 1.0))) return putRoot(x, key, val);
if (cmp < 0) x->left = put(x->left, key, val);
else x->right = put(x->right, key, val);
fix(x);
return x;
}
Node * putRoot(Node * x, Index key, Value val) {
if (!x) return new Node(key, val);
int cmp = compare(key, x->key);
if (!cmp)
{
x->val = val;
return x;
}
if (cmp < 0) { x->left = putRoot(x->left, key, val); x = rotR(x); }
else { x->right = putRoot(x->right, key, val); x = rotL(x); }
return x;
}
Node * select(Node * x, int& k)
{ // Return Node containing key of rank k.
if(!x) return 0;
int t = size(x->left);
if (t > k) return select(x->left, k);
else if (t < k) return select(x->right, k-t-1);
else return x;
}
/*************************************************************************
* deletion
*************************************************************************/
Node * joinLR(Node * a, Node * b) {
if (!a) return b;
if (!b) return a;
if (rnd.bernoulli((double) size(a) / (size(a) + size(b)))) {
a->right = joinLR(a->right, b);
fix(a);
return a;
}
else {
b->left = joinLR(a, b->left);
fix(b);
return b;
}
}
Node * remove(Node * h, Index key) {
if (!h) return 0;
int cmp = compare(key, h->key);
if (cmp < 0) h->left = remove(h->left, key);
else if (cmp > 0) h->right = remove(h->right, key);
else h = joinLR(h->left, h->right);
fix(h);
return h;
}
/*************************************************************************
* helper BST functions
*************************************************************************/
// fix auxilliar information (subtree count and max fields)
void fix(Node * x) {
if (!x) return;
x->N = 1 + size(x->left) + size(x->right);
}
// right rotate
Node * rotR(Node * h) {
Node * x = h->left;
h->left = x->right;
x->right = h;
fix(h);
fix(x);
return x;
}
// left rotate
Node * rotL(Node * h) {
Node * x = h->right;
h->right = x->left;
x->left = h;
fix(h);
fix(x);
return x;
}
int compare(Index& v, Index& w) const
{
if (v > w) return 1;
else if(v < w) return -1;
else return 0;
}
};
/***********************************************************************
* Iterate using inorder traversal using a stack.
* Iterating through N elements takes O(N) time.
***********************************************************************/
template<typename Index, typename Value>
class BSTIterator
{
typedef typename BST<Index, Value>::Node Node;
public:
BSTIterator(Node * x)
{
do_push(x);
if (stack.Empty())
_cur = 0;
else
{
x = stack.Top();
stack.Pop();
_cur = x;
do_push(x->right);
}
}
void operator = (const BSTIterator& it)
{
stack = it.stack;
_cur = it._cur;
}
bool operator == (const BSTIterator& it)
{
return _cur == it._cur;
}
bool operator != (const BSTIterator& it)
{
return _cur != it._cur;
}
BSTIterator& operator ++ ()
{
if (isEnd())
{
_cur = 0;
return *this;
}
Node * x = stack.Top(); stack.Pop();
_cur = x;
do_push(x->right);
return *this;
}
Index operator * () const { return _cur->key; }
private:
Stack<Node *> stack;
Node * _cur;
bool isEnd() { return stack.Empty(); }
void do_push(Node * x)
{
while (x)
{
stack.Push(x);
x = x->left;
}
}
};
int main()
{
BST<std::string, std::string> st;
st.put("www.cs.princeton.edu", "128.112.136.11");
st.put("www.cs.princeton.edu", "128.112.136.35");
st.put("www.princeton.edu", "128.112.130.211");
st.put("www.math.princeton.edu", "128.112.18.11");
st.put("www.yale.edu", "130.132.51.8");
st.put("www.amazon.com", "207.171.163.90");
st.put("www.simpsons.com", "209.123.16.34");
st.put("www.stanford.edu", "171.67.16.120");
st.put("www.google.com", "64.233.161.99");
std::cout << st.get("www.cs.princeton.edu") << std::endl;
std::cout << st.get("www.princeton.edu") << std::endl;
BST<std::string, std::string>::iterator it = st.begin();
while(it != st.end())
{
std::cout << *it << " " << st.get(*it) << std::endl;
++it;
}
}
Random.h#ifndef RANDOM_H
#define RANDOM_H
// Random class
// This code assumes 32-bit ints,
// which are standard on modern compilers.
//
// CONSTRUCTION: with (a) no initializer or (b) an integer
// that specifies the initial state of the generator
//
// ******************PUBLIC OPERATIONS*********************
// Return a random number according to some distribution:
// int randomInt( ) --> Uniform, 1 to 2^31-1
// int random0_1( ) --> Uniform, 0 to 1
// int randomInt( int low, int high ) --> Uniform low..high
class Random
{
public:
explicit Random( int initialValue = 1 );
int randomInt( );
double random0_1( );
int randomInt( int low, int high );
bool bernoulli( double p );
private:
int state;
};
//Implementations
static const int A = 48271;
static const int M = 2147483647;
static const int Q = M / A;
static const int R = M % A;
/**
* Construct with initialValue for the state.
*/
Random::Random( int initialValue )
{
if( initialValue < 0 )
initialValue += M;
state = initialValue;
if( state == 0 )
state = 1;
}
/**
* Return a pseudorandom int, and change the
* internal state.
*/
inline int Random::randomInt( )
{
int tmpState = A * ( state % Q ) - R * ( state / Q );
if( tmpState >= 0 )
state = tmpState;
else
state = tmpState + M;
return state;
}
/**
* Return a pseudorandom double in the open range 0..1
* and change the internal state.
*/
inline double Random::random0_1( )
{
return static_cast<double>( randomInt() ) / M;
}
/**
* Return an int in the closed range [low,high], and
* change the internal state. This is a poor implementation and
* will be biased toward some numbers, especially if the range is large.
*/
inline int Random::randomInt( int low, int high )
{
double partitionSize = static_cast<double>( M ) / ( high - low + 1 );
return static_cast<int>( randomInt() / partitionSize ) + low;
}
/**
* Returns a bool, which is true with probability p, and false otherwise.
*/
inline bool Random::bernoulli(double p)
{
if (!(p >= 0.0 && p <= 1.0))
throw "Probability must be between 0.0 and 1.0";
return random0_1() < p;
}
#endif
stack.h#pragma once
#include <cassert>
const int maxStack=16;
template<class T>
class Stack
{
public:
Stack():_top(0){}
void Push(T i);
void Pop();
T Top() const;
bool Empty() const;
private:
T _arr [maxStack];
int _top;
};
template<class T>
void Stack<T>::Push(T i)
{
assert (_top<maxStack);
_arr [_top]=i;
++_top;
}
template<class T>
void Stack<T>::Pop()
{
assert (_top>0);
--_top;
}
template<class T>
T Stack<T>::Top()const
{
assert (_top>0);
return _arr [_top-1];
}
template<class T>
bool Stack<T>::Empty() const
{
return !_top;
}
这三个文件就是一个完整的随机化二叉树
还有一个随机化二叉树的应用,区间树。#include <iostream>
#include <cassert>
#include "Random.h"
class Interval1D
{
public:
const int low; // left endpoint
const int high; // right endpoint
Interval1D(int left, int right)
:low(left), high(right)
{}
bool intersects(Interval1D& that) {
if (that.high < low) return false;
if (high < that.low) return false;
return true;
}
bool contains(int x) {
return (low <= x) && (x <= high);
}
int compareTo(Interval1D& that) {
if (low < that.low) return -1;
else if (low > that.low) return +1;
else if (high < that.high) return -1;
else if (high < that.high) return +1;
else return 0;
}
};
class IntervalST
{
typedef int Value;
struct Node
{
Node(Interval1D i, Value v)
:inv(i), val(v), left(0),
right(0), N(1), max(i.high)
{}
Interval1D inv; // key
Value val; // associated data
Node *left, *right; // left and right subtrees
int N; // size of subtree rooted at this node
int max; // max endpoint in subtree rooted at this node
};
public:
IntervalST(): root(0) {}
/*************************************************************************
* BST search
*************************************************************************/
bool contains(Interval1D& inv) {
return get(inv) != 0;
}
// return value associated with the given key
// if no such value, return null
Value get(Interval1D& inv) {
return get(root, inv);
}
/*************************************************************************
* randomized insertion
*************************************************************************/
void put(Interval1D inv, Value val) {
if (contains(inv))
{ std::cout << "duplicate" << std::endl; remove(inv); }
root = randomizedInsert(root, inv, val);
}
// remove and return value associated with given interval;
// if no such interval exists return null
Value remove(Interval1D inv) {
Value value = get(inv);
root = remove(root, inv);
return value;
}
// return an interval in data structure that intersects the given inteval;
// return null if no such interval exists
// running time is proportional to log N
Interval1D search(Interval1D& inv) {
return search(root, inv);
}
// look in subtree rooted at x
Interval1D search(Node * x, Interval1D inv) {
while (!x) {
if (inv.intersects(x->inv)) return x->inv;
else if (!x->left) x = x->right;
else if (x->left->max < inv.low) x = x->right;
else x = x->left;
}
return Interval1D(0, 0);
}
// return *all* intervals in data structure that intersect the given interval
// running time is proportional to R log N, where R is the number of intersections
void searchAll(Interval1D& inv) { searchAll(root, inv); }
// look in subtree rooted at x
bool searchAll(Node * x, Interval1D inv) {
bool found1 = false;
bool found2 = false;
bool found3 = false;
if (!x)
return false;
if (inv.intersects(x->inv)) {
std::cout << '[' << x->inv.low
<< ',' << x->inv.high << "]\n";
found1 = true;
}
if (x->left && x->left->max >= inv.low)
found2 = searchAll(x->left, inv);
if (found2 || !x->left || x->left->max < inv.low)
found3 = searchAll(x->right, inv);
return found1 || found2 || found3;
}
int size() { return size(root); }
int height() { return height(root); }
private:
Node * root;
Random rnd;
int size(Node * x) {
if (!x) return 0;
else return x->N;
}
int height(Node * x) {
if (!x) return 0;
return 1 + (height(x->left) > height(x->right)
? height(x->left) : height(x->right));
}
//Private methods
Value get(Node *x, Interval1D& inv)
{
if (!x) return 0;
int cmp = inv.compareTo(x->inv);
if (cmp < 0) return get(x->left, inv);
else if (cmp > 0) return get(x->right, inv);
else return x->val;
}
// make new node the root with uniform probability
Node * randomizedInsert(Node * x, Interval1D inv, Value val) {
if (!x) return new Node(inv, val);
if (rnd.random0_1() * size(x) < 1.0) return rootInsert(x, inv, val);
int cmp = inv.compareTo(x->inv);
if (cmp < 0) x->left = randomizedInsert(x->left, inv, val);
else x->right = randomizedInsert(x->right, inv, val);
fix(x);
return x;
}
Node * rootInsert(Node * x, Interval1D inv, Value val) {
if (!x) return new Node(inv, val);
int cmp = inv.compareTo(x->inv);
if (cmp < 0) { x->left = rootInsert(x->left, inv, val); x = rotR(x); }
else { x->right = rootInsert(x->right, inv, val); x = rotL(x); }
return x;
}
/*************************************************************************
* deletion
*************************************************************************/
Node * joinLR(Node * a, Node * b) {
if (!a) return b;
if (!b) return a;
if (rnd.random0_1() * (size(a) + size(b)) < size(a)) {
a->right = joinLR(a->right, b);
fix(a);
return a;
}
else {
b->left = joinLR(a, b->left);
fix(b);
return b;
}
}
Node * remove(Node * h, Interval1D inv) {
if (!h) return 0;
int cmp = inv.compareTo(h->inv);
if (cmp < 0) h->left = remove(h->left, inv);
else if (cmp > 0) h->right = remove(h->right, inv);
else h = joinLR(h->left, h->right);
fix(h);
return h;
}
/*************************************************************************
* helper BST functions
*************************************************************************/
// fix auxilliar information (subtree count and max fields)
void fix(Node * x) {
if (!x) return;
x->N = 1 + size(x->left) + size(x->right);
x->max = max3(x->inv.high, max(x->left), max(x->right));
}
int max(Node * x) {
if (!x) return -1;
return x->max;
}
// precondition: a is not null
int max3(int a, int b, int c) {
int max = ( a < b ) ? b : a;
return ( ( max < c ) ? c : max );
}
// right rotate
Node * rotR(Node * h) {
Node * x = h->left;
h->left = x->right;
x->right = h;
fix(h);
fix(x);
return x;
}
// left rotate
Node * rotL(Node * h) {
Node * x = h->right;
h->right = x->left;
x->left = h;
fix(h);
fix(x);
return x;
}
};
int main()
{
IntervalST st;
Random rand_inv;
for (int i = 0; i < 50; i++) {
int low = rand_inv.randomInt(0, 1000);
int high = rand_inv.randomInt(0, 50) + low;
Interval1D interval(low, high);
st.put(interval, i);
}
Interval1D ready(400, 700);
st.searchAll(ready);
}
大家学习参考一下。
|
|