C语言 从红黑树中删除大量节点导致无限循环

n9vozmp4  于 2023-05-16  发布在  其他
关注(0)|答案(1)|浏览(77)

我一直在用C(Red Black Tree Node Insertion Overwrites Previously Added Node)开发RedBlack Tree实现,遇到了一个问题,在大量删除(~1000+到~2000+)之后,它陷入了无限循环。
RB删除代码:

typedef struct TreeNode TreeNode;
struct TreeNode {
  TreeNode *parent;
  TreeNode *child[2];
  COLOR color;
  U64 blockSize; // 'key'
  void *data;
};

typedef struct Tree Tree;
struct Tree {
  TreeNode *root;
  TreeNode *nil; 
};

... 
void transplant(Tree *tree, TreeNode *u, TreeNode *v) {
  if (u->parent == tree->nil) {
    tree->root = v;
  } else if (u == u->parent->left) {
    u->parent->left = v;
  } else {
    u->parent->right = v;
  }
  
  v->parent = u->parent;
}

void delete_fix(Tree *tree, TreeNode *x) {
  TreeNode *w = tree->nil;
  while (x != tree->root && x->color == BLACK) {
    if (x == x->parent->left) {
      w = x->parent->right;
      
      if (w->color == RED) {
        w->color = BLACK;
        x->parent->color = RED;
        left_rotate(tree, x->parent);
        w = x->parent->right;
      }
      
      if (w->left->color == BLACK && w->right->color == BLACK) {
        w->color = RED;
        x = x->parent;
      } else {
        if (w->right->color == BLACK) {
          w->left->color = BLACK;
          w->color = BLACK;
          right_rotate(tree, w);
          w = x->parent->right;
        }
        
        w->color = x->parent->color;
        x->parent->color = BLACK;
        w->right->color = BLACK;
        left_rotate(tree, x->parent);
        
        x = tree->root;
      }
    } else {
      w = x->parent->left;
      
      if (w->color == RED) {
        w->color = BLACK;
        x->parent->color = RED;
        right_rotate(tree, x->parent);
        w = x->parent->left;
      }
      
      if (w->right->color == BLACK && w->left->color == BLACK) {
        w->color = RED;
        x = x->parent;
      } else {
        if (w->left->color == BLACK) {
          w->right->color = BLACK;
          w->color = BLACK;
          left_rotate(tree, w);
          w = x->parent->left;
        }
        
        w->color = x->parent->color;
        x->parent->color = BLACK;
        w->left->color = BLACK;
        right_rotate(tree, x->parent);
        
        x = tree->root;
      }
    }
  }
  
  x->color = BLACK;
}

void delete_node(Tree *tree, TreeNode *z) {
  if (tree != NIL && z != tree->nil && z != tree->nil) {
    TreeNode *x = tree->nil, *y = z;
    COLOR yOgColor = y->color;
    
    if (z->left == tree->nil) {
      x = z->right;
      transplant(tree, z, z->right);
    } else if (z->right == tree->nil) {
      x = z->left;
      transplant(tree, z, z->left);
    } else {
      y = minimum(tree, z->right);
      yOgColor = y->color;
      x = y->right;
      if (y->parent == z) {
        x->parent = y;
      } else {
        transplant(tree, y, y->right);
        y->right = z->right;
        y->right->parent = y;
      }
      
      transplant(tree, z, y);
      y->left = z->left;
      y->left->parent = y;
      y->color = z->color;
    }
    if (yOgColor == BLACK) {
      delete_fix(tree, x);
    }
  }
}

TreeNode *minimum(Tree *t, TreeNode *x) {
  while (x->left != t->nil) {
    x = x->left;
  }
  
  return (x);
}

我已经缩小了它进入无限循环的范围,但主要的罪魁祸首必须在delete_node实现的其余部分:

TreeNode *minimum(Tree *t, TreeNode *x) {
  while (x->left != t->nil) {
    x = x->left;
  }
  
  return (x);
}

驱动程序代码

U64 myrandom(U64 range) {
  U64 num;
  num = rand() % range;
  return num;
}

void print_inorder(FILE *file, Tree *t, TreeNode *n) {
  if (n != t->nil) {
    print_inorder(file, t, n->left);
    fprintf(file, "%llu \n", n->blockSize);
    print_inorder(file, t, n->right);
  }
}

int main(void) {
  
  srand(time(NULL));
  
  printf("Hello Tree\n");
  Tree tree = {0};
  TreeNode nil = {0};
  
  nil.parent = NIL;
  nil.left = &nil;
  nil.right = &nil;
  nil.color = BLACK;
  nil.blockSize = 0;
  
  tree.nil = tree.root = &nil;
  Tree *ptr = &tree;
  
  LARGE_INTEGER frequency;
  LARGE_INTEGER start;
  LARGE_INTEGER end;
  double interval;
  
  QueryPerformanceFrequency(&frequency);
  QueryPerformanceCounter(&start);
  
  
  TreeNode nodes[20000];
  
  for (int i = 0; i < 20000; i++) {
    TreeNode n = {0};
    n.parent = NIL;
    n.left = NIL;
    n.right = NIL;
    n.color = BLACK;
    n.blockSize = myrandom(UINT_FAST64_MAX);
    
    nodes[i] = n;
  }
  
  QueryPerformanceCounter(&start);
  for (int i = 0; i < 20000; i++) {
    insert_node(ptr, &nodes[i]);
  }
  QueryPerformanceCounter(&end);
  interval = (double) (end.QuadPart - start.QuadPart) / frequency.QuadPart;
  FILE *preDelFilePtr = fopen("rb_test_pre_delete.txt", "wb");
  fprintf(preDelFilePtr, "************************\n");
  fprintf(preDelFilePtr, "*      pre delete      *\n");
  fprintf(preDelFilePtr, "************************\n");
  fprintf(preDelFilePtr, "* time spent: %f *\n", interval);
  fprintf(preDelFilePtr, "************************\n");
  print_inorder(preDelFilePtr, ptr, ptr->root);
  
  
  frequency.QuadPart = 0;
  start.QuadPart = 0;
  end.QuadPart = 0;
  interval = 0;
  QueryPerformanceCounter(&start);
  for (int i = 0; i <= 10000; i++) {
    U64 removeIndex = myrandom(20000); 
    if (&nodes[removeIndex] != ptr->nil)
    {
      delete_node(ptr, &nodes[removeIndex]);
    }
  }
  QueryPerformanceCounter(&end);
  interval = (double) (end.QuadPart - start.QuadPart) / frequency.QuadPart;
  FILE *postDelFilePtr = fopen("rb_test_post_delete.txt", "wb");
  fprintf(postDelFilePtr, "************************\n");
  fprintf(postDelFilePtr, "*     post delete      *\n");
  fprintf(postDelFilePtr, "************************\n");
  fprintf(postDelFilePtr, "* time spent: %f *\n", interval);
  fprintf(postDelFilePtr, "************************\n");
  print_inorder(postDelFilePtr, ptr, ptr->root);
  
  fclose(preDelFilePtr);
  fclose(postDelFilePtr);
  
  return 0;
}

到目前为止,我已经尝试在minimum函数的开头添加一些检查,但这也没有解决问题。
任何帮助或意见将不胜感激!
更新:
下面是更新后的完整源代码,现在使用NULL而不是tree->nil来表示叶节点。
main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <windows.h>

#include "rb.h"

U64 myrandom(U64 range) {
  U64 num;
  num = rand() % range;
  return num;
}

void print_inorder(FILE *file, Tree *t, TreeNode *n) {
  if (n != NULL) {
    print_inorder(file, t, n->left);
    fprintf(file, "%llu \n", n->blockSize);
    print_inorder(file, t, n->right);
  }
}

int main(void) {
  
  srand(time(NULL));
  
  printf("Hello Tree\n");
  Tree tree = {0};
  Tree *ptr = &tree;
  

  TreeNode nodes[20000];
  
  for (int i = 0; i < 20000; i++) {
    TreeNode n = {0};
    n.parent = NULL;
    n.left = NULL;
    n.right = NULL;
    n.color = BLACK;
    n.blockSize = myrandom(UINT_FAST64_MAX);
    
    nodes[i] = n;
  }
  
 
  FILE *preDelFilePtr = fopen("rb_test_pre_delete.txt", "wb");
  fprintf(preDelFilePtr, "************************\n");
  fprintf(preDelFilePtr, "*      pre delete      *\n");
  print_inorder(preDelFilePtr, ptr, ptr->root);
  
  
  FILE *postDelFilePtr = fopen("rb_test_post_delete.txt", "wb");
  fprintf(postDelFilePtr, "************************\n");
  fprintf(postDelFilePtr, "*     post delete      *\n");
  print_inorder(postDelFilePtr, ptr, ptr->root);
  
  fclose(preDelFilePtr);
  fclose(postDelFilePtr);
  
  return 0;
}

rb.h

#ifndef RB_H
#define RB_H

#include <inttypes.h>

typedef enum COLOR { BLACK, RED } COLOR;

#ifndef U64_TYPE
#define U64_TYPE
typedef uint_fast64_t U64;
#endif

typedef struct TreeNode TreeNode;
struct TreeNode {
  TreeNode *parent;
  TreeNode *child[2];
  COLOR color;
  U64 blockSize; // 'key'
  void *data;
};

typedef struct Tree Tree;
struct Tree {
  TreeNode *root;
};

#define LEFT 0
#define RIGHT 1
#define left child[LEFT]
#define right child[RIGHT]

void left_rotate(Tree *tree, TreeNode *node);
void right_rotate(Tree *tree, TreeNode *node);
void insert_fix(Tree *tree, TreeNode *node);
void insert_node(Tree *tree, TreeNode *toInsert);
void transplant(Tree *tree, TreeNode *n1, TreeNode *n2);
void delete_fix(Tree *tree, TreeNode *node);
void delete_node(Tree *tree, TreeNode *node);
TreeNode *maximum(TreeNode *node);
TreeNode *minimum(TreeNode *node);

void left_rotate(Tree *tree, TreeNode *node) {
  if (tree != NULL && node != NULL) {
    TreeNode *rightChild = node->right;
    node->right = rightChild->left;
    
    if (rightChild->left != NULL) {
      rightChild->left->parent = node;
    }
    
    rightChild->parent = node->parent;
    
    if (node->parent == NULL) {
      tree->root = rightChild;
    } else if (node == node->parent->left) {
      node->parent->left = rightChild;
    } else {
      node->parent->right = rightChild;
    }
    
    rightChild->left = node;
    
    node->parent = rightChild;
  }
}

void right_rotate(Tree *tree, TreeNode *node) {
  if (tree != NULL && node != NULL) {
    TreeNode *leftChild = node->left;
    node->left = leftChild->right;
    
    if (leftChild->right != NULL) {
      leftChild->right->parent = node;
    }
    
    leftChild->parent = node->parent;
    
    if (node->parent == NULL) {
      tree->root = leftChild;
    } else if (node == node->parent->right) {
      node->parent->right = leftChild;
    } else {
      node->parent->left = leftChild;
    }
    
    leftChild->right = node;
    
    node->parent = leftChild;
  }
}

void insert_fix(Tree *tree, TreeNode *z) {
  // iterate until z is not the root and z's parent color is red
  if (z->parent != NULL)
  {
    while (z != tree->root && z->parent != NULL && z->parent->color == RED) {
      if (z->parent->parent != NULL)
      {
        if (z->parent == z->parent->parent->left &&
            z->parent->parent->right != NULL) {
          TreeNode *y = z->parent->parent->right;
          {
            if (y->color == RED) {
              z->parent->color = BLACK;
              y->color = BLACK;
              z->parent->parent->color = RED;
              z = z->parent->parent;
            } else {
              if (z == z->parent->right) {
                z = z->parent;
                left_rotate(tree, z);
              }
              z->parent->color = BLACK;
              z->parent->color = RED;
              right_rotate(tree, z->parent->parent);
            }
          }
        } else if (z->parent == z->parent->parent->right &&
                   z->parent->parent->left != NULL) {
          TreeNode *y = z->parent->parent->left;
          if (y->color == RED) {
            z->parent->color = BLACK;
            y->color = BLACK;
            z->parent->parent->color = RED;
            z = z->parent->parent;
          } else {
            if (z == z->parent->left) {
              z = z->parent;
              right_rotate(tree, z);
            }
            z->parent->color = BLACK;
            z->parent->color = RED;
            left_rotate(tree, z->parent->parent);
          }
        } else {
          break;
        }
      } else {
        break;
      }
    }
    tree->root->color = BLACK;
  }// keep root always black
}

void insert_node(Tree *tree, TreeNode *z) {
  if (tree != NULL) {
    TreeNode *y = NULL;
    TreeNode *x = tree->root;
    
    while (x != NULL) {
      y = x;
      
      if (z->blockSize < x->blockSize) {
        x = x->left;
      } else {
        x = x->right;
      }
    }
    
    z->parent = y;
    
    if (y == NULL) {
      tree->root = z;
    } else if (z->blockSize < y->blockSize) {
      y->left = z;
    } else {
      y->right = z;
    }
    
    z->left = NULL;
    z->right = NULL;
    z->color = RED;
    insert_fix(tree, z);
  }
}

void transplant(Tree *tree, TreeNode *u, TreeNode *v) {
  if (v != NULL)
  {
    if (u->parent == NULL) {
      tree->root = v;
    } else if (u == u->parent->left) {
      u->parent->left = v;
    } else {
      u->parent->right = v;
    }
    
    v->parent = u->parent;
  }
}

void delete_fix(Tree *tree, TreeNode *x) {
  TreeNode *w = NULL;
  if (x != NULL)
  {
    while (x != tree->root && x->color == BLACK) {
      if (x->parent != NULL)
      {
        if (x == x->parent->left) {
          w = x->parent->right;
          
          if (w->color == RED) {
            w->color = BLACK;
            x->parent->color = RED;
            left_rotate(tree, x->parent);
            w = x->parent->right;
          }
          
          if (w->left != NULL && w->right != NULL)
          {
            if (w->left->color == BLACK && w->right->color == BLACK) {
              w->color = RED;
              x = x->parent;
            } else {
              if (w->right != NULL)
              {
                if (w->right->color == BLACK) {
                  w->left->color = BLACK;
                  w->color = BLACK;
                  right_rotate(tree, w);
                  w = x->parent->right;
                }
              }
              w->color = x->parent->color;
              x->parent->color = BLACK;
              w->right->color = BLACK;
              left_rotate(tree, x->parent);
              
              x = tree->root;
            }
          }
        } else {
          w = x->parent->left;
          
          if (w->color == RED) {
            w->color = BLACK;
            x->parent->color = RED;
            right_rotate(tree, x->parent);
            w = x->parent->left;
          }
          
          if (w->left != NULL && w->right != NULL)
          {
            if (w->right->color == BLACK && w->left->color == BLACK) {
              w->color = RED;
              x = x->parent;
            } else {
              if (w->left->color == BLACK) {
                w->right->color = BLACK;
                w->color = BLACK;
                left_rotate(tree, w);
                w = x->parent->left;
              }
              
              w->color = x->parent->color;
              x->parent->color = BLACK;
              w->left->color = BLACK;
              right_rotate(tree, x->parent);
              
              x = tree->root;
            }
          }
        }
      } else {
        break;
      }
    }
    
    x->color = BLACK;
  }
}

void delete_node(Tree *tree, TreeNode *z) {
  if (tree != NULL && z != NULL && z != NULL) {
    TreeNode *x = NULL, *y = z;
    COLOR yOgColor = y->color;
    
    if (z->left == NULL) {
      x = z->right;
      transplant(tree, z, z->right);
    } else if (z->right == NULL) {
      x = z->left;
      transplant(tree, z, z->left);
    } else {
      y = minimum(z->right);
      yOgColor = y->color;
      x = y->right;
      if (x != NULL)
      {
        if (x->parent != NULL && y->parent == z) {
          x->parent = y;
        } else {
          transplant(tree, y, y->right);
          y->right = z->right;
          y->right->parent = y;
        }
      }
      transplant(tree, z, y);
      y->left = z->left;
      y->left->parent = y;
      y->color = z->color;
    }
    if (yOgColor == BLACK) {
      delete_fix(tree, x);
    }
  }
}

TreeNode *maximum(TreeNode *x) {
  while (x->right != NULL) {
    x = x->right;
  }
  
  return (x);
}

TreeNode *minimum(TreeNode *x) {
  while (x->left != NULL) {
    x = x->left;
  }
  
  return (x);
}

#endif //RB_H
iqih9akk

iqih9akk1#

我发现插入的逻辑有错误,所以这个需要先解决。但是,我并没有试图找出插入和删除逻辑中的所有错误,而是想从头开始重写它,并且在以下方面采取了稍微不同的方法:

  • 不要在主程序中创建节点,但是让与树相关的函数接受 values 而不是节点,并让它们根据需要创建,查找和处理节点。
  • 利用child数组,可以在左/右镜像场景中使用相同的代码。
  • 添加一个函数来打印带有缩进的树,这样就有了一些树结构的视觉感觉
  • 添加一个函数来验证树是否为有效的红黑树,包括检查:
  • 父子链接的一致性(节点的父节点应该将该节点作为子节点)
  • BST属性(节点的键分隔其子树的范围)
  • 红色属性(红色节点不能有红色父节点)
  • black属性(从给定节点到其子树中任何叶子节点的每条路径都必须有相同数量的黑色节点)

代码如下:

#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

typedef enum COLOR { BLACK, RED } COLOR;

#ifndef U64_TYPE
#define U64_TYPE
typedef uint_fast64_t U64;
#endif

typedef struct TreeNode TreeNode;
struct TreeNode {
  TreeNode *parent;
  TreeNode *child[2];
  COLOR color;
  U64 blockSize; // 'key'
  void *data;
};

typedef struct Tree Tree;
struct Tree {
  TreeNode *root;
};

int child_side(TreeNode *node) { // Return 1 when the node is its parent right-child, 0 otherwise
    return node->parent && node->parent->child[1] == node;
}

void set_child(Tree *tree, TreeNode *node, int side, TreeNode *child) {
    if (node) {
        node->child[side] = child;
    } else {
        tree->root = child;
    }
    if (child) {
        child->parent = node;
    }
}

void rotate(Tree *tree, TreeNode *node, int side) {
    TreeNode *risingChild = node->child[1-side]; // the child that will move one level up
    set_child(tree, node, 1-side, risingChild->child[side]);
    set_child(tree, node->parent, child_side(node), risingChild);
    set_child(tree, risingChild, side, node);
}

void insert_fix(Tree *tree, TreeNode *node) {
    TreeNode *parent = node->parent;
    node->color = parent ? RED : BLACK;
    if (parent && parent->color == RED) { // red violation
        tree->root->color = BLACK;
        // We have a red-violation as both node and its parent are red.
        TreeNode *grandparent = parent->parent; // Guaranteed to be not NULL
        int side = child_side(parent);
        TreeNode *uncle = grandparent->child[1-side];
        if (uncle && uncle->color == RED) {
            // Parent and Uncle are red
            parent->color = uncle->color = BLACK;
            return insert_fix(tree, grandparent); // repeat using recursion
        }
        // Uncle is black (or NULL)
        if (node == parent->child[1-side]) { // Node is inner grandchild?
            // Node is inner grandchild: turn it into an outer-grandchild configuration 
            rotate(tree, parent, side); // Node is lifted above parent
            node = parent; // swap the naming of the rotated nodes, so node is the lower one
            parent = node->parent;
        }
        // Node is outer grandchild
        rotate(tree, grandparent, 1-side);
        parent->color = BLACK;
        grandparent->color = RED;
    }
}

TreeNode* create_node(U64 blockSize) {
    TreeNode *node = malloc(sizeof(*node));
    node->parent = node->child[0] = node->child[1] = node->data = NULL;
    node->color = BLACK;
    node->blockSize = blockSize;
    return node;
}

TreeNode* find_node(Tree *tree, U64 blockSize) {
    TreeNode *node = NULL;
    TreeNode *curr = tree->root;
    
    while (curr != NULL) {
        node = curr;
        if (node->blockSize == blockSize) {
            break;
        }
        curr = curr->child[blockSize > curr->blockSize];
    }
    return node;
}

void insert_value(Tree *tree, U64 blockSize) {
    TreeNode *leaf = find_node(tree, blockSize);
    // Duplicates not allowed (we could, but then better combine in one node)
    if (!leaf || leaf->blockSize != blockSize) {
        TreeNode *node = create_node(blockSize);
        set_child(tree, leaf, leaf && blockSize > leaf->blockSize, node);
        insert_fix(tree, node);
    }
}

TreeNode *minimum(TreeNode *node) {
    while (node->child[0]) {
        node = node->child[0];
    }
    return node;
}

TreeNode* swap_content(TreeNode *a, TreeNode *b) {
    // Swap data
    void *data= a->data;
    a->data = b->data;
    b->data = data;
    // Swap key
    U64 blockSize = a->blockSize;
    a->blockSize = b->blockSize;
    b->blockSize = blockSize;
    return b;
}

void free_node(TreeNode *node) {
    free(node->data);
    free(node);
}

void delete_fix(Tree *tree, TreeNode *parent, int side) {
    if (!parent) {
        return;
    }
    
    TreeNode *sibling = parent->child[1-side]; // has black height >= 1
    TreeNode *close_nephew = sibling->child[side];

    if (sibling->color == RED) {
        // Case D3: Sibling is red
        rotate(tree, parent, side);
        parent->color = RED;
        sibling->color = BLACK;
        sibling = close_nephew;
        close_nephew = sibling->child[side];
    }
    // Sibling is black
    TreeNode *distant_nephew = sibling->child[1-side];
    if (distant_nephew && distant_nephew->color == RED) {
        // Case D6: distant nephew is red
        rotate(tree, parent, side);
        sibling->color = parent->color;
        parent->color = distant_nephew->color = BLACK;
        return;
    }
    // Distant nephew is not red
    sibling->color = RED; // common action for cases D2, D4, D5
    if (close_nephew && close_nephew->color == RED) {
        // Case D5: close nephew is red
        rotate(tree, sibling, 1-side);
        rotate(tree, parent, side);
        close_nephew->color = parent->color;
        parent->color = sibling->color = BLACK;
        return;
    }
    // Nephews are not red
    if (parent->color == BLACK) {
        // Case D2: Parent is black
        return delete_fix(tree, parent->parent, child_side(parent));
    }
    // Case D4: parent is red    
    parent->color = BLACK;
}

void delete_node(Tree *tree, TreeNode *node) {
    if (node->child[0] && node->child[1]) {
        node = swap_content(node, minimum(node->child[1]));
    }
    TreeNode *child = node->child[!node->child[0]];
    if (node->color == BLACK && child) {
        child->color = BLACK;
    }
    int side = child_side(node);
    set_child(tree, node->parent, side, child);
    if (node->color == BLACK && !child) {
        delete_fix(tree, node->parent, side);
    }
    free_node(node);
}

int delete_value(Tree *tree, U64 blockSize) {
    TreeNode *node = find_node(tree, blockSize);
    if (node) { // found
        delete_node(tree, node);
        return 1;
    }
    return 0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////

void print_inorder(Tree *t, TreeNode *n, int depth) {
  if (n != NULL) {
    print_inorder(t, n->child[1], depth + 1);
    printf("%*s%lu %c \n", 1+depth*2, " ", n->blockSize, n->color == BLACK ? 'B' : 'r');
    print_inorder(t, n->child[0], depth + 1);
  }
}

void print_tree(Tree *t) {
    print_inorder(t, t->root, 0);
}

int verify_subtree(TreeNode *node, U64 low, U64 high) {
    if (!node) {
        return 0; // OK. Return number of BLACK
    }
    if (node->blockSize < low || node->blockSize > high) {
        printf("node %lu violates BST property. window is (%lu,%lu).\n", node->blockSize, low, high);
        exit(1);
    }
    if (node->parent && node->parent->child[child_side(node)] != node) {
        printf("node %lu is not a child of its parent (inconsistency).\n", node->blockSize);
        exit(1);
    }
    if ((!node->parent || node->parent->color == RED) && node->color == RED) {
        printf("node %lu violates red property.\n", node->blockSize);
        exit(1);
    }
    int black_count1 = verify_subtree(node->child[0], low, node->blockSize);
    int black_count2 = verify_subtree(node->child[1], node->blockSize, high);
    if (black_count1 != black_count2) {
        printf("subtree %lu violates black property.\n", node->blockSize);
        exit(1);
    }
    return black_count1 + (node->color == BLACK);
}

void verify_tree(Tree *tree) {
    verify_subtree(tree->root, 0, 1000000);
}

void shuffle(U64 *array, size_t n) {
    size_t i;
    for (size_t i = 0; i < n - 1; i++) 
    {
      size_t j = i + rand() / (RAND_MAX / (n - i) + 1);
      U64 t = array[j];
      array[j] = array[i];
      array[i] = t;
    }
}

int main(void) {
    Tree tree = {0};
    srand(time(NULL));

    size_t n = 200;
    U64 array[n];
    for (U64 i = 0; i < n; i++) {
        array[i] = i;
    }
    shuffle(array, n);
    
    for (size_t i = 0; i < n; i++) {
        insert_value(&tree, array[i]);
        verify_tree(&tree);
    }
    print_tree(&tree);
    verify_tree(&tree);

    shuffle(array, n);

    for (size_t i = 0; i < n; i++) {
        if (!delete_value(&tree, array[i])) {
            printf("Did not find value %lu in the tree", array[i]);
            exit(1);
        }
        verify_tree(&tree);
    }
    print_tree(&tree);
    return 0;
}

相关问题