diff anagram/support/agbaltree-imp.h @ 0:13d2b8934445

Import AnaGram (near-)release tree into Mercurial.
author David A. Holland
date Sat, 22 Dec 2007 17:52:45 -0500
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/anagram/support/agbaltree-imp.h	Sat Dec 22 17:52:45 2007 -0500
@@ -0,0 +1,590 @@
+/**********************************************************
+
+The AnaGram Class Library
+
+The AgBalancedTree Class
+Copyright 1997 Parsifal Software. All Rights Reserved.
+See the file COPYING for license and usage terms.
+
+***********************************************************/
+
+#ifndef AGBALTREE_IMP_H
+#define AGBALTREE_IMP_H
+
+#include "minmax.h"
+
+
+template <class T>
+void *AgBalancedTree<T>::Node::operator new(size_t n) {
+  return malloc(n);
+}
+
+template <class T>
+void AgBalancedTree<T>::Node::operator delete(void *p) {
+  free(p);
+}
+
+template <class T>
+AgBalancedTree<T>::Node::Node (const T &t)
+  : left(0), right(0), data(t), count(1)
+{
+}
+
+
+template <class T>
+AgBalancedTree<T>::~AgBalancedTree() {
+  delete root;
+}
+
+template <class T>
+AgBalancedTree<T>::Node::~Node() {
+  //nodesDeleted++;
+  //LOGV(nodesDeleted);
+  delete left;
+  delete right;
+}
+
+
+template <class T>
+AgBalancedTree<T> &AgBalancedTree<T>::reset() {
+  delete root;
+  root = 0;
+  return *this;
+}
+
+template <class T>
+int AgBalancedTree<T>::operator < (const AgBalancedTree<T> &t) const {
+  int n = min(size(), t.size());
+  int i = 0;
+  while (i < n) {
+    if ((*this)[i] < t[i]) {
+      return 1;
+    }
+    if (t[i] < (*this)[i]) {
+      return 0;
+    }
+    i++;
+  }
+  return size() < t.size();
+}
+
+template <class T>
+void AgBalancedTree<T>::Node::resetCount() {
+  count = 1;
+  if (left) {
+    count += left->count;
+  }
+  if (right) {
+    count += right->count;
+  }
+}
+
+template <class T>
+T &AgBalancedTree<T>::Node::locate(const unsigned x) const {
+  //LOGSECTION("AgBalancedTree<T>::Node::locate");
+  unsigned leftCount = left ? left->count : 0;
+  //LOGV(x) LCV(count) LCV(leftCount);
+  if (x == leftCount) {
+    return (T &) data;
+  }
+  if (x < leftCount) {
+    return left->locate(x);
+  }
+  return right->locate(x - leftCount - 1);
+}
+
+template <class T>
+int AgBalancedTree<T>::compare(const T &x, const T &y) const {
+  if (x < y) {
+    return -1;
+  }
+  return y < x;
+}
+
+template <class T>
+unsigned AgBalancedTree<T>::size() const {
+  return root != 0 ? root->count : 0;
+}
+
+template <class T>
+int AgBalancedTree<T>::includes(const T &t) const {
+  if (root) {
+    return includes(t, root);
+  }
+  else {
+    return 0;
+  }
+}
+
+template <class T>
+int AgBalancedTree<T>::lookup(T &t) const {
+  if (root) {
+    return lookup(t, root);
+  }
+  else {
+    return 0;
+  }
+}
+
+template <class T>
+int AgBalancedTree<T>::insert(const T &t) {
+  if (root) {
+    return insert(t, root);
+  }
+  root = new Node(t);
+  return 0;
+}
+
+template <class T>
+int AgBalancedTree<T>::identify(T &t) {
+  //LOGSECTION("AgBalancedTree::identify");
+  if (root) {
+    return identify(t, root);
+  }
+  root = new Node(t);
+  t = root->data;
+  return 0;
+}
+
+template <class T>
+int AgBalancedTree<T>::identify(T *&t) {
+  if (root) {
+    return identify(t, root);
+  }
+  root = new Node(*t);
+  t = &root->data;
+  return 0;
+}
+
+template <class T>
+int AgBalancedTree<T>::remove(const T &t) {
+  if (root) {
+    return remove(t, root);
+  }
+  else {
+    return 0;
+  }
+}
+
+template <class T>
+int AgBalancedTree<T>::includes(const T &target, AgBalancedTree<T>::Node *node) const {
+  int flag = compare(target, node->data);
+  if (flag == 0) {
+    return 1;
+  }
+  if (flag < 0 && node->left) {
+    return includes(target, node->left);
+  }
+  if (flag > 0 && node->right) {
+    return includes(target, node->right);
+  }
+  return 0;
+}
+
+template <class T>
+int AgBalancedTree<T>::lookup(T &target, AgBalancedTree<T>::Node *node) const {
+  int flag = compare(target, node->data);
+  if (flag == 0) {
+    target = node->data;
+    return 1;
+  }
+  if (flag < 0 && node->left) {
+    return lookup(target, node->left);
+  }
+  if (flag > 0 && node->right) {
+    return lookup(target, node->right);
+  }
+  return 0;
+}
+
+template <class T>
+AgBalancedTree<T> AgBalancedTree<T>::operator + (AgBalancedTree<T> &x) {
+  AgBalancedTree<T> setUnion;
+  int n = size();
+  while (n--) {
+    setUnion.insert((*this)[n]);
+  }
+  n = x.size();
+  while (n--) {
+    setUnion.insert(x[n]);
+  }
+  return setUnion;
+}
+
+template <class T>
+AgBalancedTree<T> AgBalancedTree<T>::operator - (AgBalancedTree<T> &x) {
+  AgBalancedTree<T> difference;
+  int n = size();
+  while (n--) {
+    difference.insert((*this)[n]);
+  }
+  n = x.size();
+  while (n--) {
+    difference.remove(x[n]);
+  }
+  return difference;
+}
+
+template <class T>
+AgBalancedTree<T> AgBalancedTree<T>::operator * (AgBalancedTree<T> &x) {
+  AgBalancedTree<T> intersection;
+  int n = size();
+  while (n--) {
+    T &element = (*this)[n];
+    if (x.includes(element)) {
+      intersection.insert(element);
+    }
+  }
+  return intersection;
+}
+
+template <class T>
+AgBalancedTree<T> &AgBalancedTree<T>::operator *= (AgBalancedTree<T> &x) {
+  int n = size();
+  while (n--) {
+    T &element = (*this)[n];
+    if (!x.includes(element)) {
+      remove(element);
+    }
+  }
+  return *this;
+}
+
+template <class T>
+int AgBalancedTree<T>::insert(const T &target, AgBalancedTree<T>::Node *&node){
+  int flag = compare(target, node->data);
+  if (flag == 0) {
+    return 1;
+  }
+  if (flag < 0 && node->left == 0) {
+    node->left = new Node(target);
+    node->count++;
+    return 0;
+  }
+  if (flag > 0 && node->right == 0) {
+    node->right = new Node(target);
+    node->count++;
+    return 0;
+  }
+
+  if (flag < 0) {
+    if (insert(target, node->left)) {
+      return 1;
+    }
+    node->count++;
+    unsigned newCount = node->left->count;
+    unsigned oldCount = newCount-1;
+    if ((oldCount^newCount) != (oldCount|newCount)) {
+      return 0;
+    }
+    unsigned rightCount = node->right ? node->right->count : 0;
+    if (newCount/2 > rightCount) {
+      rotateRight(node);
+    }
+  }
+  else {
+    if (insert(target, node->right)) {
+      return 1;
+    }
+    node->count++;
+    unsigned newCount = node->right->count;
+    unsigned oldCount = newCount-1;
+    if ((oldCount^newCount) != (oldCount|newCount)) {
+      return 0;
+    }
+    unsigned leftCount = node->left ? node->left->count : 0;
+    if (newCount/2 > leftCount) {
+      rotateLeft(node);
+    }
+  }
+  return 0;
+}
+
+template <class T>
+int AgBalancedTree<T>::identify(T &target, Node *&node) {
+  //LOGSECTION("AgBalancedTree::identify");
+  int flag = compare(target, node->data);
+  if (flag == 0) {
+    target = node->data;
+    return 1;
+  }
+  if (flag < 0 && node->left == 0) {
+    node->left = new Node(target);
+    node->count++;
+    target = node->left->data;
+    return 0;
+  }
+  if (flag > 0 && node->right == 0) {
+    node->right = new Node(target);
+    node->count++;
+    target = node->right->data;
+    return 0;
+  }
+
+  if (flag < 0) {
+    if (identify(target, node->left)) {
+      return 1;
+    }
+    node->count++;
+    unsigned newCount = node->left->count;
+    unsigned oldCount = newCount-1;
+    if ((oldCount^newCount) != (oldCount|newCount)) {
+      return 0;
+    }
+    unsigned rightCount = node->right ? node->right->count : 0;
+    if (newCount/2 > rightCount) {
+      rotateRight(node);
+    }
+  }
+  else {
+    if (identify(target, node->right)) {
+      return 1;
+    }
+    node->count++;
+    unsigned newCount = node->right->count;
+    unsigned oldCount = newCount-1;
+    if ((oldCount^newCount) != (oldCount|newCount)) {
+      return 0;
+    }
+    unsigned leftCount = node->left ? node->left->count : 0;
+    if (newCount/2 > leftCount) {
+      rotateLeft(node);
+    }
+  }
+  return 0;
+}
+
+template <class T>
+int AgBalancedTree<T>::identify(T *&target, AgBalancedTree<T>::Node *&node) {
+  int flag = compare(*target, node->data);
+  if (flag == 0) {
+    target = &node->data;
+    return 1;
+  }
+  if (flag < 0 && node->left == 0) {
+    node->left = new Node(*target);
+    node->count++;
+    target = &node->left->data;
+    return 0;
+  }
+  if (flag > 0 && node->right == 0) {
+    node->right = new Node(*target);
+    node->count++;
+    target = &node->right->data;
+    return 0;
+  }
+
+  if (flag < 0) {
+    if (identify(target, node->left)) {
+      return 1;
+    }
+    node->count++;
+    unsigned newCount = node->left->count;
+    unsigned oldCount = newCount-1;
+    if ((oldCount^newCount) != (oldCount|newCount)) {
+      return 0;
+    }
+    unsigned rightCount = node->right ? node->right->count : 0;
+    if (newCount/2 > rightCount) {
+      rotateRight(node);
+    }
+  }
+  else {
+    if (identify(target, node->right)) {
+      return 1;
+    }
+    node->count++;
+    unsigned newCount = node->right->count;
+    unsigned oldCount = newCount-1;
+    if ((oldCount^newCount) != (oldCount|newCount)) {
+      return 0;
+    }
+    unsigned leftCount = node->left ? node->left->count : 0;
+    if (newCount/2 > leftCount) {
+      rotateLeft(node);
+    }
+  }
+  return 0;
+}
+
+template <class T>
+int AgBalancedTree<T>::remove(const T &target, AgBalancedTree<T>::Node *&node){
+  int flag = compare(target, node->data);
+  if (flag < 0 && node->left) {
+    unsigned oldCount = node->left->count;
+    if (remove(target, node->left) == 0) {
+      return 0;
+    }
+    node->count--;
+    unsigned newCount = oldCount - 1;
+    if ((oldCount^newCount) != (oldCount|newCount)) {
+      return 1;
+    }
+    unsigned rightCount = node->right ? node->right->count : 0;
+    if (rightCount/2 > newCount) {
+      rotateLeft(node);
+    }
+    return 1;
+  }
+  if (flag > 0 && node->right) {
+    unsigned oldCount = node->right->count;
+    if (remove(target, node->right) == 0) {
+      return 0;
+    }
+    node->count--;
+    unsigned newCount = oldCount - 1;
+    if ((oldCount^newCount) != (oldCount|newCount)) {
+      return 1;
+    }
+    unsigned leftCount = node->left ? node->left->count : 0;
+    if (leftCount/2 > newCount) {
+      rotateRight(node);
+    }
+    return 1;
+  }
+
+  if (flag) {
+    return 0;
+  }
+  if (node->count == 1) {
+    delete node;
+    node = 0;
+    return 1;
+  }
+
+  unsigned leftCount = node->left ? node->left->count : 0;
+  unsigned rightCount = node->right ? node->right->count : 0;
+  Node *replacement;
+  if (rightCount > leftCount) {
+    replacement = extractMin(node->right);
+  }
+  else {
+    replacement = extractMax(node->left);
+  }
+  replacement->left = node->left;
+  replacement->right = node->right;
+  node->left = node->right = 0;
+  delete node;
+  replacement->resetCount();
+  node = replacement;
+  return 1;
+}
+
+template <class T>
+void AgBalancedTree<T>::rotateLeft(AgBalancedTree<T>::Node *&node) {
+  Node *nRL = node->right->left;
+  Node *nRR = node->right->right;
+  unsigned leftCount = nRL ? nRL->count : 0;
+  unsigned rightCount = nRR ? nRR->count : 0;
+  if (leftCount < rightCount) {
+    Node *replacement = node->right;
+    Node *orphan = replacement->left;
+
+    replacement->left = node;
+
+    node->right = orphan;
+    node->resetCount();
+
+    node = replacement;
+    node->resetCount();
+    return;
+  }
+  Node *replacement = nRL;
+  Node *leftOrphan = replacement->left;
+  Node *rightOrphan = replacement->right;
+
+  replacement->right = node->right;
+  replacement->right->left = rightOrphan;
+  replacement->right->resetCount();
+
+  replacement->left = node;
+  replacement->left->right = leftOrphan;
+  replacement->left->resetCount();
+
+  node = replacement;
+  node->resetCount();
+}
+
+template <class T>
+void AgBalancedTree<T>::rotateRight(AgBalancedTree<T>::Node *&node) {
+  Node *nLR = node->left->right;
+  Node *nLL = node->left->left;
+  unsigned leftCount = nLL ? nLL->count : 0;
+  unsigned rightCount = nLR ? nLR->count : 0;
+  if (rightCount < leftCount) {
+    Node *replacement = node->left;
+    Node *orphan = replacement->right;
+
+    replacement->right = node;
+
+    node->left = orphan;
+    node->resetCount();
+
+    node = replacement;
+    node->resetCount();
+    return;
+  }
+  Node *replacement = nLR;
+  Node *leftOrphan = replacement->left;
+  Node *rightOrphan = replacement->right;
+
+  replacement->left = node->left;
+  replacement->left->right = leftOrphan;
+  replacement->left->resetCount();
+
+  replacement->right = node;
+  replacement->right->left = rightOrphan;
+  replacement->right->resetCount();
+
+  node = replacement;
+  node->resetCount();
+}
+
+template <class T>
+typename AgBalancedTree<T>::Node *
+AgBalancedTree<T>::extractMin(typename AgBalancedTree<T>::Node *&node) {
+  Node *result;
+  if (node->left) {
+    unsigned oldCount = node->left->count;
+    result = extractMin(node->left);
+    node->count--;
+    unsigned newCount = oldCount - 1;
+    if ((oldCount^newCount) != (oldCount|newCount)) {
+      return result;
+    }
+    unsigned rightCount = node->right ? node->right->count : 0;
+    if (rightCount/2 > newCount) {
+      rotateLeft(node);
+    }
+    return result;
+  }
+  result = node;
+  node = node->right;
+  return result;
+}
+
+template <class T>
+typename AgBalancedTree<T>::Node *
+AgBalancedTree<T>::extractMax(typename AgBalancedTree<T>::Node *&node) {
+  Node *result;
+  if (node->right) {
+    unsigned oldCount = node->right->count;
+    result = extractMax(node->right);
+    node->count--;
+    unsigned newCount = oldCount - 1;
+    if ((oldCount^newCount) != (oldCount|newCount)) {
+      return result;
+    }
+    unsigned leftCount = node->left ? node->left->count : 0;
+    if (leftCount/2 > newCount) {
+      rotateRight(node);
+    }
+    return result;
+  }
+  result = node;
+  node = node->left;
+  return result;
+}
+
+
+#endif /* AGBALTREE_IMP_H */