Двоичное дерево поиска, проблема с кодированием

#binary-search-tree

#двоичное дерево поиска

Вопрос:

По какой-то странной причине мое дерево BST на самом деле работает не так, как ожидалось, это код, который я создал:

 #include lt;stdio.hgt; #include lt;time.hgt; #include lt;stdlib.hgt; #include lt;limits.hgt;  //Creating the main structure of the main BST Tree struct treeNode{  int key; //The key of the node  struct treeNode *leftChild; //The left child of the node  struct treeNode *rightChild; //The right child of the node  struct treeNode *parent; //The parent of the node };  //Function for implementing and creating a new node in the BST struct treeNode* newNode(int x){  struct treeNode *n;  n = malloc(sizeof(struct treeNode));  n-gt;key = x;  n-gt;leftChild = NULL;  n-gt;rightChild = NULL;  n-gt;parent = NULL;   return n;  }  //Function for finding the minimun value in a treeNode struct treeNode* BSTTreeMin(struct treeNode *root){    if(root-gt;leftChild == NULL){  return root; //if the left child is nil, return the root  }  else{  return BSTTreeMin(root-gt;leftChild); //otherwise we repeform the same operation on the left child  } }  //Function for searching a specific node in the BST struct treeNode* BSTTreeSearch(struct treeNode *root,int x){  if(root == NULL || root-gt;key == x){  return root; //if root corresponds to key then the element x is found   }  if(x lt; root-gt;key){  return BSTTreeSearch(root-gt;leftChild, x); // in the case where the element x is smaller than root--gt;key then it searches the left child  }  else{  return BSTTreeSearch(root-gt;rightChild, x);// in the opposite case, it searches the right child  } }  //function for inserting a new key in the BST struct treeNode* BSTTreeInsert(struct treeNode *root, struct treeNode *z){  struct treeNode *y = NULL;  struct treeNode *x = root;  while(x != NULL){  y = x;  if(z-gt;key lt;= x-gt;key){  x = x-gt;leftChild;  }  else{  x = x-gt;rightChild;  }  }  z-gt;parent = y;  if(y == NULL){  root = z;  }  else if(root != NULL amp;amp; z-gt;key lt;= y-gt;key){  y-gt;leftChild = z;  }  else{  y-gt;rightChild = z;  } }  struct treeNode* BSTTreeTransplant(struct treeNode *root, struct treeNode *u, struct treeNode *v){  if(u-gt;parent == NULL){  root = v;  }  else if(u == u-gt;parent-gt;leftChild){  u-gt;parent-gt;leftChild = v;  }  else{  u-gt;parent-gt;rightChild = v;  }  if(v != NULL){  v-gt;parent = u-gt;parent;  } } //function for delete a node in a BST struct treeNode* BSTTreeDelete(struct treeNode *root, struct treeNode *z){  if(z-gt;leftChild == NULL){  BSTTreeTransplant(root, z, z-gt;rightChild);  }  else if(z-gt;rightChild == NULL){  BSTTreeTransplant(root, z, z-gt;leftChild);  }  else{  struct treeNode *y = BSTTreeMin(z-gt;rightChild);  if(y-gt;parent != z){  BSTTreeTransplant(root, y, y-gt;rightChild);  y-gt;rightChild = z-gt;rightChild;  y-gt;rightChild-gt;parent = y;  }  BSTTreeTransplant(root, z, y);  y-gt;leftChild = z-gt;leftChild;  y-gt;leftChild-gt;parent = y;  } }  //Function for emptying a BST void BSTTreeDeallocate(struct treeNode *root){  if(root == NULL){  return;  }  BSTTreeDeallocate(root-gt;leftChild);  BSTTreeDeallocate(root-gt;rightChild);  free(root); }  //function that checks if the Bst is valid (antagonistic function) int isValidBstHelper(struct treeNode *root, int low, int high) {  return root == NULL ||   (root-gt;key gt;= low amp;amp; root-gt;key lt;= high amp;amp;  isValidBstHelper(root-gt;leftChild, low, root-gt;key) amp;amp;  isValidBstHelper(root-gt;rightChild, root-gt;key, high));  }  //function that initiate the validity check of the Bst int isValidBst(struct treeNode *root) {  return isValidBstHelper(root, INT_MIN, INT_MAX); }  //Main experiment function for this program, calculating the time for inserting, deleting and searching nodes in our BST double SingleExperiment(int max_keys,double max_search,double max_delete,int max_instances){  double t_tot = 0;  int i;  int key;  double search;  double delete;   for(i = 1; i lt;= max_instances; i  ){  clock_t start_t, end_t;    srand(0);  struct treeNode *root;  root = newNode(rand()); // Initializing the root of the tree   struct treeNode *i = newNode(rand());  struct treeNode *d = newNode(rand());   start_t = clock();  for(key = 1; key lt;= max_keys; key  ){  BSTTreeInsert(root,i); //Starting with the insertion of the nodes  }  for(search = 1; search lt;= max_search; search  ){  BSTTreeSearch(root, rand()); //Following by the searching of the nodes  }  for(delete = 1; delete lt;= max_delete; delete  ){  BSTTreeDelete(root, d); //Finally, the deletion of the nodes  }   end_t = clock();  double t_elapsed = (double)(end_t - start_t); //Calculation of the time elapased  t_tot  = t_elapsed; //Adding the time to the total time   //inorder(root); //checks if the BST is in order --gt; prints an ordered array   //Checking if the Bst is valid  if (isValidBst(root)) {  printf("The tree is a valid BST n");  } else {  printf("The tree is NOT a valid BST n");  }   BSTTreeDeallocate(root); //Emptying the tree   }  return t_tot/max_keys; //Returning the average time }  //main function (represents the experiment function) int main(void){   int min_keys = 5;  int max_keys = 10;  int max_instances = 5;  int percentage_search = 60;  int keys;  int seed = 0;  //setting up the main parameters for the experiment   printf("Binary Search Tree n");  for(keys = min_keys; keys lt;= max_keys; keys = keys  1){  srand(seed);  double max_search = keys * percentage_search / 100;  double max_delete = keys - max_search;   double time = SingleExperiment(keys,max_search,max_delete,max_instances);  printf("%d %fn",keys,time);//printing the time associate to each key value    seed = seed  1;  }   return 0;  }  

результатом должно быть «дерево допустимо» для каждой итерации и общее время для каждого отдельного номера ключа. Всякий раз, когда я запускаю программу, она выводит только «Дерево двоичного поиска» и ничего больше. Не могли бы вы, пожалуйста, любезно помочь мне?

Заранее всем спасибо!

Комментарии:

1. С этим кодом много проблем. Вы, безусловно, можете точно определить с помощью отладки, где что-то может пойти не так. Пожалуйста, приложите усилия для отладки.

Ответ №1:

Основная проблема возникает в этом цикле:

 for(key = 1; key lt;= max_keys; key  ){  BSTTreeInsert(root,i);  }  

Игнорирование этого i является плохим выбором в качестве имени переменной для узла (оно уже используется в качестве переменной цикла), это приведет к повторной вставке одного и того же узла. Это означает, что вторая итерация этого цикла вставит узел, который уже находится в дереве. Это сделает узел его собственным дочерним (самоназвание). Как следствие, третья итерация этого цикла никогда не достигнет листа в дереве, так как он продолжает следовать этой ссылке на себя, бегая по кругу.

Быстрое решение состоит в том, чтобы вставлять новые узлы на каждой итерации:

 for(key = 1; key lt;= max_keys; key  ){  BSTTreeInsert(root, newNode(rand());  }  

Теперь это устраняет вашу проблему, но все же я хотел бы отметить, что остальная часть кода эксперимента на самом деле не очень полезна:

  • BSTTreeSearch очень, очень вероятно, что функция будет вызываться со значениями, которые не встречаются в дереве, и не проверяется, действительно ли функция возвращает ожидаемый результат. Но тогда также должны быть положительные тесты-чтобы увидеть, действительно ли найдены значения, которые находятся в дереве.
  • BSTTreeDelete вызывается повторно с одним и тем же узлом. Более того, этот узел никогда не вставлялся в дерево, поэтому эти вызовы никогда не удалят какой-либо узел из дерева.

Возможно, вы захотите улучшить это, но это выходит за рамки вашего вопроса.