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

📄 rbtree.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器-Cisco router simulator, used to fake a 7200 series can be simulated
💻 C
字号:
/* * Dynamips * Copyright (c) 2005 Christophe Fillot. * E-mail: cf@utc.fr * * rbtree.c: Red/Black Trees. */static const char rcsid[] = "$Id$";#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdarg.h>#include <unistd.h>#include <errno.h>#include <signal.h>#include <fcntl.h>#include <ctype.h>#include "utils.h"#include "rbtree.h"#define rbtree_nil(tree) (&(tree)->nil)#define NIL(tree,x)      (((x) == rbtree_nil(tree)) || !x)/* Allocate memory for a new node */static rbtree_node *rbtree_node_alloc(rbtree_tree *tree,void *key,void *value){   rbtree_node *node;   if (!(node = mp_alloc_n0(&tree->mp,sizeof(*node))))      return NULL;   node->key = key;   node->value = value;   node->left = rbtree_nil(tree);   node->right = rbtree_nil(tree);   node->parent = rbtree_nil(tree);   node->color = -1;   return node;}/* Free memory used by a node */static inline void rbtree_node_free(rbtree_tree *tree,rbtree_node *node){   mp_free(node);}/* Returns the node which represents the minimum value */static inline rbtree_node *rbtree_min(rbtree_tree *tree,rbtree_node *x){   while(!NIL(tree,x->left))      x = x->left;   return(x);}/* Returns the node which represents the maximum value */static inline rbtree_node *rbtree_max(rbtree_tree *tree,rbtree_node *x){   while(!NIL(tree,x->right))      x = x->right;   return(x);}/* Returns the successor of a node */static inline rbtree_node *rbtree_successor(rbtree_tree *tree,rbtree_node *x){   rbtree_node *y;   if (!NIL(tree,x->right))      return(rbtree_min(tree,x->right));   y = x->parent;   while(!NIL(tree,y) && (x == y->right)) {      x = y;      y = y->parent;   }   return(y);}/* Left rotation */static inline void rbtree_left_rotate(rbtree_tree *tree,rbtree_node *x){   rbtree_node *y;   y = x->right;   x->right = y->left;   if (!NIL(tree,x->right))      x->right->parent = x;   y->parent = x->parent;      if (NIL(tree,x->parent))      tree->root = y;   else {      if (x == x->parent->left)         x->parent->left = y;      else         x->parent->right = y;   }   y->left = x;   x->parent = y;}/* Right rotation */static inline void rbtree_right_rotate(rbtree_tree *tree,rbtree_node *y){   rbtree_node *x;   x = y->left;   y->left = x->right;   if (!NIL(tree,y->left))      y->left->parent = y;   x->parent = y->parent;   if (NIL(tree,y->parent))      tree->root = x;   else {      if (y->parent->left == y)         y->parent->left = x;      else         y->parent->right = x;   }   x->right = y;   y->parent = x;}/* insert a new node */static rbtree_node *rbtree_insert_new(rbtree_tree *tree,void *key,void *value,                                      int *exists){   rbtree_node *parent,*node,*new_node,**nodeplace;   int comp;   nodeplace = &tree->root;   parent = NULL;   *exists = FALSE;      for(;;)    {      node = *nodeplace;      if (NIL(tree,node))         break;      comp = tree->key_cmp(key,node->key,tree->opt_data);      if (!comp) {         *exists = TRUE;         node->value = value;         return node;      }      parent = node;      nodeplace = (comp > 0) ? &node->right : &node->left;   }   /* create a new node */   if (!(new_node = rbtree_node_alloc(tree,key,value)))      return NULL;   *nodeplace = new_node;   new_node->parent = parent;   tree->node_count++;   return new_node;}/* Insert a node in a Red/Black Tree */int rbtree_insert(rbtree_tree *tree,void *key,void *value){   rbtree_node *x,*y;   int exists;   /* insert a new node (if necessary) */   x = rbtree_insert_new(tree,key,value,&exists);   if (exists) return(0);   if (!x) return(-1);   tree->node_count++;   /* maintains red-black properties */   x->color = RBTREE_RED;   while((x != tree->root) && (x->parent->color == RBTREE_RED))   {      if (x->parent == x->parent->parent->left)      {         y = x->parent->parent->right;         if (y->color == RBTREE_RED)          {            x->parent->color = RBTREE_BLACK;            y->color = RBTREE_BLACK;            x->parent->parent->color = RBTREE_RED;            x = x->parent->parent;         }         else         {            if (x == x->parent->right) {               x = x->parent;               rbtree_left_rotate(tree,x);            }            x->parent->color = RBTREE_BLACK;            x->parent->parent->color = RBTREE_RED;            rbtree_right_rotate(tree,x->parent->parent);         }      }      else      {         y = x->parent->parent->left;         if (y->color == RBTREE_RED)          {            x->parent->color = RBTREE_BLACK;            y->color = RBTREE_BLACK;            x->parent->parent->color = RBTREE_RED;            x = x->parent->parent;         }         else         {            if (x == x->parent->left) {               x = x->parent;               rbtree_right_rotate(tree,x);            }            x->parent->color = RBTREE_BLACK;            x->parent->parent->color = RBTREE_RED;            rbtree_left_rotate(tree,x->parent->parent);         }      }   }   tree->root->color = RBTREE_BLACK;   return(0);}/* Lookup for a node corresponding to "key" */static inline rbtree_node *rbtree_lookup_node(rbtree_tree *tree,void *key){   rbtree_node *node;   int comp;   node = tree->root;   for (;;) {      if (NIL(tree,node)) /* key not found */         break;      if (!(comp = tree->key_cmp(key,node->key,tree->opt_data)))         break; /* exact match */      node = (comp > 0) ? node->right : node->left;   }      return(node);}/*  * Lookup for a node corresponding to "key". If node does not exist,  * function returns null pointer. */void *rbtree_lookup(rbtree_tree *tree,void *key){   return(rbtree_lookup_node(tree,key)->value);}/* Restore Red/black tree properties after a removal */static void rbtree_removal_fixup(rbtree_tree *tree,rbtree_node *x){   rbtree_node *w;   while((x != tree->root) && (x->color == RBTREE_BLACK))   {      if (x == x->parent->left)      {         w = x->parent->right;         if (w->color == RBTREE_RED) {            w->color = RBTREE_BLACK;            x->parent->color = RBTREE_RED;            rbtree_left_rotate(tree,x->parent);            w = x->parent->right;         }         if ((w->left->color == RBTREE_BLACK) &&             (w->right->color == RBTREE_BLACK))         {            w->color = RBTREE_RED;            x = x->parent;         }         else         {            if (w->right->color == RBTREE_BLACK) {               w->left->color = RBTREE_BLACK;               w->color = RBTREE_RED;               rbtree_right_rotate(tree,w);               w = x->parent->right;            }            w->color = x->parent->color;            x->parent->color = RBTREE_BLACK;            w->right->color = RBTREE_BLACK;            rbtree_left_rotate(tree,x->parent);            x = tree->root;         }      }      else      {         w = x->parent->left;         if (w->color == RBTREE_RED) {            w->color = RBTREE_BLACK;            x->parent->color = RBTREE_RED;            rbtree_right_rotate(tree,x->parent);            w = x->parent->left;         }         if ((w->right->color == RBTREE_BLACK) &&             (w->left->color == RBTREE_BLACK))         {            w->color = RBTREE_RED;            x = x->parent;         }         else         {            if (w->left->color == RBTREE_BLACK) {               w->right->color = RBTREE_BLACK;               w->color = RBTREE_RED;               rbtree_left_rotate(tree,w);               w = x->parent->left;            }            w->color = x->parent->color;            x->parent->color = RBTREE_BLACK;            w->left->color = RBTREE_BLACK;            rbtree_right_rotate(tree,x->parent);            x = tree->root;         }      }   }   x->color = RBTREE_BLACK;}/* Removes a node out of a tree */void *rbtree_remove(rbtree_tree *tree,void *key){   rbtree_node *z = rbtree_lookup_node(tree,key);   rbtree_node *x,*y;   void *value;      if (NIL(tree,z))      return NULL;      value = z->value;   if (NIL(tree,z->left) || NIL(tree,z->right))      y = z;   else      y = rbtree_successor(tree,z);   if (!NIL(tree,y->left))      x = y->left;   else      x = y->right;   x->parent = y->parent;   if (NIL(tree,y->parent))      tree->root = x;   else {      if (y == y->parent->left)         y->parent->left = x;      else         y->parent->right = x;   }   if (y != z) {      z->key = y->key;      z->value = y->value;   }   if (y->color == RBTREE_BLACK)      rbtree_removal_fixup(tree,x);   rbtree_node_free(tree,y);   tree->node_count++;   return(value);}static void rbtree_foreach_node(rbtree_tree *tree,rbtree_node *node,                                tree_fforeach user_fn,void *opt){   if (!NIL(tree,node)) {      rbtree_foreach_node(tree,node->left,user_fn,opt);      user_fn(node->key,node->value,opt);      rbtree_foreach_node(tree,node->right,user_fn,opt);   }}/* Call the specified function for each node */int rbtree_foreach(rbtree_tree *tree,tree_fforeach user_fn,void *opt){   if (!tree) return(-1);   rbtree_foreach_node(tree,tree->root,user_fn,opt);   return(0);}/* Returns the maximum height of the right and left sub-trees */static int rbtree_height_node(rbtree_tree *tree,rbtree_node *node){   int lh,rh;   lh = (!NIL(tree,node->left)) ? rbtree_height_node(tree,node->left) : 0;   rh = (!NIL(tree,node->right)) ? rbtree_height_node(tree,node->right) : 0;   return(1 + m_max(lh,rh));}/* Compute the height of a Red/Black tree */int rbtree_height(rbtree_tree *tree){   return(!NIL(tree,tree->root) ? rbtree_height_node(tree,tree->root) : 0);}/* Returns the number of nodes */int rbtree_node_count(rbtree_tree *tree){   return(tree->node_count);}/* Purge all nodes */void rbtree_purge(rbtree_tree *tree){   mp_free_all_blocks(&tree->mp);   tree->node_count = 0;   /* just in case */   memset(rbtree_nil(tree),0,sizeof(rbtree_node));   rbtree_nil(tree)->color = RBTREE_BLACK;   /* reset root */   tree->root = rbtree_nil(tree);}/* Check a node */static int rbtree_check_node(rbtree_tree *tree,rbtree_node *node){   if (!NIL(tree,node)) return(0);   if (!NIL(tree,node->left)) {      if (tree->key_cmp(node->key,node->left->key,tree->opt_data) <= 0)         return(-1);            if (rbtree_check_node(tree,node->left) == -1)         return(-1);   }   if (!NIL(tree,node->right)) {      if (tree->key_cmp(node->key,node->right->key,tree->opt_data) >= 0)         return(-1);      if (rbtree_check_node(tree,node->right) == -1)         return(-1);   }   return(0);}/* Check tree consistency */int rbtree_check(rbtree_tree *tree){   return(rbtree_check_node(tree,tree->root));}/* Create a new Red/Black tree */rbtree_tree *rbtree_create(tree_fcompare key_cmp,void *opt_data){   rbtree_tree *tree;   if (!(tree = malloc(sizeof(*tree))))      return NULL;   memset(tree,0,sizeof(*tree));   /* initialize the memory pool */   if (!mp_create_fixed_pool(&tree->mp,"Red-Black Tree")) {      free(tree);      return NULL;   }   /* initialize the "nil" pointer */   memset(rbtree_nil(tree),0,sizeof(rbtree_node));   rbtree_nil(tree)->color = RBTREE_BLACK;   tree->key_cmp = key_cmp;   tree->opt_data = opt_data;   tree->root = rbtree_nil(tree);   return tree;}/* Delete a Red/Black tree */void rbtree_delete(rbtree_tree *tree){   if (tree) {      mp_free_pool(&tree->mp);      free(tree);   }}

⌨️ 快捷键说明

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