⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 avlmap.ccp

📁 早期freebsd实现
💻 CCP
字号:
// This may look like C code, but it is really -*- C++ -*-/* Copyright (C) 1988 Free Software Foundation    written by Doug Lea (dl@rocky.oswego.edu)This file is part of the GNU C++ Library.  This library is freesoftware; you can redistribute it and/or modify it under the terms ofthe GNU Library General Public License as published by the FreeSoftware Foundation; either version 2 of the License, or (at youroption) any later version.  This library is distributed in the hopethat it will be useful, but WITHOUT ANY WARRANTY; without even theimplied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULARPURPOSE.  See the GNU Library General Public License for more details.You should have received a copy of the GNU Library General PublicLicense along with this library; if not, write to the Free SoftwareFoundation, 675 Mass Ave, Cambridge, MA 02139, USA.*/#ifdef __GNUG__#pragma implementation#endif#include <stream.h>#include "<T>.<C>.AVLMap.h"/* constants & inlines for maintaining balance & thread status in tree nodes*/#define AVLBALANCEMASK    3#define AVLBALANCED       0#define AVLLEFTHEAVY      1#define AVLRIGHTHEAVY     2#define LTHREADBIT        4#define RTHREADBIT        8static inline int bf(<T><C>AVLNode* t){  return t->stat & AVLBALANCEMASK;}static inline void set_bf(<T><C>AVLNode* t, int b){  t->stat = (t->stat & ~AVLBALANCEMASK) | (b & AVLBALANCEMASK);}static inline int rthread(<T><C>AVLNode* t){  return t->stat & RTHREADBIT;}static inline void set_rthread(<T><C>AVLNode* t, int b){  if (b)    t->stat |= RTHREADBIT;  else    t->stat &= ~RTHREADBIT;}static inline int lthread(<T><C>AVLNode* t){  return t->stat & LTHREADBIT;}static inline void set_lthread(<T><C>AVLNode* t, int b){  if (b)    t->stat |= LTHREADBIT;  else    t->stat &= ~LTHREADBIT;}/* traversal primitives*/<T><C>AVLNode* <T><C>AVLMap::leftmost(){  <T><C>AVLNode* t = root;  if (t != 0) while (t->lt != 0) t = t->lt;  return t;}<T><C>AVLNode* <T><C>AVLMap::rightmost(){  <T><C>AVLNode* t = root;  if (t != 0) while (t->rt != 0) t = t->rt;  return t;}<T><C>AVLNode* <T><C>AVLMap::succ(<T><C>AVLNode* t){  <T><C>AVLNode* r = t->rt;  if (!rthread(t)) while (!lthread(r)) r = r->lt;  return r;}<T><C>AVLNode* <T><C>AVLMap::pred(<T><C>AVLNode* t){  <T><C>AVLNode* l = t->lt;  if (!lthread(t)) while (!rthread(l)) l = l->rt;  return l;}Pix <T><C>AVLMap::seek(<T&> key){  <T><C>AVLNode* t = root;  if (t == 0)    return 0;  for (;;)  {    int cmp = <T>CMP(key, t->item);    if (cmp == 0)      return Pix(t);    else if (cmp < 0)    {      if (lthread(t))        return 0;      else        t = t->lt;    }    else if (rthread(t))      return 0;    else      t = t->rt;  }}/* The combination of threads and AVL bits make adding & deleting interesting, but very awkward. We use the following statics to avoid passing them around recursively*/static int _need_rebalancing;   // to send back balance info from rec. callsstatic <T>*   _target_item;     // add/del_item targetstatic <T><C>AVLNode* _found_node; // returned added/deleted nodestatic int    _already_found;   // for deletion subcasesvoid <T><C>AVLMap:: _add(<T><C>AVLNode*& t){  int cmp = <T>CMP(*_target_item, t->item);  if (cmp == 0)  {    _found_node = t;    return;  }  else if (cmp < 0)  {    if (lthread(t))    {      ++count;      _found_node = new <T><C>AVLNode(*_target_item, def);      set_lthread(_found_node, 1);      set_rthread(_found_node, 1);      _found_node->lt = t->lt;      _found_node->rt = t;      t->lt = _found_node;      set_lthread(t, 0);      _need_rebalancing = 1;    }    else      _add(t->lt);    if (_need_rebalancing)    {      switch(bf(t))      {      case AVLRIGHTHEAVY:        set_bf(t, AVLBALANCED);        _need_rebalancing = 0;        return;      case AVLBALANCED:        set_bf(t, AVLLEFTHEAVY);        return;      case AVLLEFTHEAVY:        <T><C>AVLNode* l = t->lt;        if (bf(l) == AVLLEFTHEAVY)        {          if (rthread(l))            t->lt = l;          else            t->lt = l->rt;          set_lthread(t, rthread(l));          l->rt = t;          set_rthread(l, 0);          set_bf(t, AVLBALANCED);          set_bf(l, AVLBALANCED);          t = l;          _need_rebalancing = 0;        }        else        {          <T><C>AVLNode* r = l->rt;          set_rthread(l, lthread(r));          if (lthread(r))            l->rt = r;          else            l->rt = r->lt;          r->lt = l;          set_lthread(r, 0);          set_lthread(t, rthread(r));          if (rthread(r))            t->lt = r;          else            t->lt = r->rt;          r->rt = t;          set_rthread(r, 0);          if (bf(r) == AVLLEFTHEAVY)            set_bf(t, AVLRIGHTHEAVY);          else            set_bf(t, AVLBALANCED);          if (bf(r) == AVLRIGHTHEAVY)            set_bf(l, AVLLEFTHEAVY);          else            set_bf(l, AVLBALANCED);          set_bf(r, AVLBALANCED);          t = r;          _need_rebalancing = 0;          return;        }      }    }  }  else  {    if (rthread(t))    {      ++count;      _found_node = new <T><C>AVLNode(*_target_item, def);      set_rthread(t, 0);      set_lthread(_found_node, 1);      set_rthread(_found_node, 1);      _found_node->lt = t;      _found_node->rt = t->rt;      t->rt = _found_node;      _need_rebalancing = 1;    }    else      _add(t->rt);    if (_need_rebalancing)    {      switch(bf(t))      {      case AVLLEFTHEAVY:        set_bf(t, AVLBALANCED);        _need_rebalancing = 0;        return;      case AVLBALANCED:        set_bf(t, AVLRIGHTHEAVY);        return;      case AVLRIGHTHEAVY:        <T><C>AVLNode* r = t->rt;        if (bf(r) == AVLRIGHTHEAVY)        {          if (lthread(r))            t->rt = r;          else            t->rt = r->lt;          set_rthread(t, lthread(r));          r->lt = t;          set_lthread(r, 0);          set_bf(t, AVLBALANCED);          set_bf(r, AVLBALANCED);          t = r;          _need_rebalancing = 0;        }        else        {          <T><C>AVLNode* l = r->lt;          set_lthread(r, rthread(l));          if (rthread(l))            r->lt = l;          else            r->lt = l->rt;          l->rt = r;          set_rthread(l, 0);          set_rthread(t, lthread(l));          if (lthread(l))            t->rt = l;          else            t->rt = l->lt;          l->lt = t;          set_lthread(l, 0);          if (bf(l) == AVLRIGHTHEAVY)            set_bf(t, AVLLEFTHEAVY);          else            set_bf(t, AVLBALANCED);          if (bf(l) == AVLLEFTHEAVY)            set_bf(r, AVLRIGHTHEAVY);          else            set_bf(r, AVLBALANCED);          set_bf(l, AVLBALANCED);          t = l;          _need_rebalancing = 0;          return;        }      }    }  }}    <C>& <T><C>AVLMap::operator [] (<T&> item){  if (root == 0)  {    ++count;    root = new <T><C>AVLNode(item, def);    set_rthread(root, 1);    set_lthread(root, 1);    return root->cont;  }  else  {    _target_item = &item;    _need_rebalancing = 0;    _add(root);    return _found_node->cont;  }}void <T><C>AVLMap::_del(<T><C>AVLNode* par, <T><C>AVLNode*& t){  int comp;  if (_already_found)  {    if (rthread(t))      comp = 0;    else      comp = 1;  }  else     comp = <T>CMP(*_target_item, t->item);  if (comp == 0)  {    if (lthread(t) && rthread(t))    {      _found_node = t;      if (t == par->lt)      {        set_lthread(par, 1);        par->lt = t->lt;      }      else      {        set_rthread(par, 1);        par->rt = t->rt;      }      _need_rebalancing = 1;      return;    }    else if (lthread(t))    {      _found_node = t;      <T><C>AVLNode* s = succ(t);      if (s != 0 && lthread(s))        s->lt = t->lt;      t = t->rt;      _need_rebalancing = 1;      return;    }    else if (rthread(t))    {      _found_node = t;      <T><C>AVLNode* p = pred(t);      if (p != 0 && rthread(p))        p->rt = t->rt;      t = t->lt;      _need_rebalancing = 1;      return;    }    else                        // replace item & find someone deletable    {      <T><C>AVLNode* p = pred(t);      t->item = p->item;      t->cont = p->cont;      _already_found = 1;      comp = -1;                // fall through below to left    }  }  if (comp < 0)  {    if (lthread(t))      return;    _del(t, t->lt);    if (!_need_rebalancing)      return;    switch (bf(t))    {    case AVLLEFTHEAVY:      set_bf(t, AVLBALANCED);      return;    case AVLBALANCED:      set_bf(t, AVLRIGHTHEAVY);      _need_rebalancing = 0;      return;    case AVLRIGHTHEAVY:      <T><C>AVLNode* r = t->rt;      switch (bf(r))      {      case AVLBALANCED:        if (lthread(r))          t->rt = r;        else          t->rt = r->lt;        set_rthread(t, lthread(r));        r->lt = t;        set_lthread(r, 0);        set_bf(t, AVLRIGHTHEAVY);        set_bf(r, AVLLEFTHEAVY);        _need_rebalancing = 0;        t = r;        return;      case AVLRIGHTHEAVY:        if (lthread(r))          t->rt = r;        else          t->rt = r->lt;        set_rthread(t, lthread(r));        r->lt = t;        set_lthread(r, 0);        set_bf(t, AVLBALANCED);        set_bf(r, AVLBALANCED);        t = r;        return;      case AVLLEFTHEAVY:        <T><C>AVLNode* l = r->lt;        set_lthread(r, rthread(l));        if (rthread(l))          r->lt = l;        else          r->lt = l->rt;        l->rt = r;        set_rthread(l, 0);        set_rthread(t, lthread(l));        if (lthread(l))          t->rt = l;        else          t->rt = l->lt;        l->lt = t;        set_lthread(l, 0);        if (bf(l) == AVLRIGHTHEAVY)          set_bf(t, AVLLEFTHEAVY);        else          set_bf(t, AVLBALANCED);        if (bf(l) == AVLLEFTHEAVY)          set_bf(r, AVLRIGHTHEAVY);        else          set_bf(r, AVLBALANCED);        set_bf(l, AVLBALANCED);        t = l;        return;      }    }  }  else  {    if (rthread(t))      return;    _del(t, t->rt);    if (!_need_rebalancing)      return;    switch (bf(t))    {    case AVLRIGHTHEAVY:      set_bf(t, AVLBALANCED);      return;    case AVLBALANCED:      set_bf(t, AVLLEFTHEAVY);      _need_rebalancing = 0;      return;    case AVLLEFTHEAVY:      <T><C>AVLNode* l = t->lt;      switch (bf(l))      {      case AVLBALANCED:        if (rthread(l))          t->lt = l;        else          t->lt = l->rt;        set_lthread(t, rthread(l));        l->rt = t;        set_rthread(l, 0);        set_bf(t, AVLLEFTHEAVY);        set_bf(l, AVLRIGHTHEAVY);        _need_rebalancing = 0;        t = l;        return;      case AVLLEFTHEAVY:        if (rthread(l))          t->lt = l;        else          t->lt = l->rt;        set_lthread(t, rthread(l));        l->rt = t;        set_rthread(l, 0);        set_bf(t, AVLBALANCED);        set_bf(l, AVLBALANCED);        t = l;        return;      case AVLRIGHTHEAVY:        <T><C>AVLNode* r = l->rt;        set_rthread(l, lthread(r));        if (lthread(r))          l->rt = r;        else          l->rt = r->lt;        r->lt = l;        set_lthread(r, 0);        set_lthread(t, rthread(r));        if (rthread(r))          t->lt = r;        else          t->lt = r->rt;        r->rt = t;        set_rthread(r, 0);        if (bf(r) == AVLLEFTHEAVY)          set_bf(t, AVLRIGHTHEAVY);        else          set_bf(t, AVLBALANCED);        if (bf(r) == AVLRIGHTHEAVY)          set_bf(l, AVLLEFTHEAVY);        else          set_bf(l, AVLBALANCED);        set_bf(r, AVLBALANCED);        t = r;        return;      }    }  }}        void <T><C>AVLMap::del(<T&> item){  if (root == 0) return;  _need_rebalancing = 0;  _already_found = 0;  _found_node = 0;  _target_item = &item;  _del(root, root);  if (_found_node)  {    delete(_found_node);    if (--count == 0)      root = 0;  }}void <T><C>AVLMap::_kill(<T><C>AVLNode* t){  if (t != 0)  {    if (!lthread(t)) _kill(t->lt);    if (!rthread(t)) _kill(t->rt);    delete t;  }}<T><C>AVLMap::<T><C>AVLMap(<T><C>AVLMap& b) :<T><C>Map(b.def){  root = 0;  count = 0;  for (Pix i = b.first(); i != 0; b.next(i))     (*this)[b.key(i)] = b.contents(i);}int <T><C>AVLMap::OK(){  int v = 1;  if (root == 0)     v = count == 0;  else  {    int n = 1;    <T><C>AVLNode* trail = leftmost();    <T><C>AVLNode* t = succ(trail);    while (t != 0)    {      ++n;      v &= <T>CMP(trail->item, t->item) < 0;      trail = t;      t = succ(t);    }    v &= n == count;  }  if (!v) error("invariant failure");  return v;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -