создание функции дерева с использованием вспомогательных функций - PullRequest
0 голосов
/ 04 марта 2020

Для класса нас попросили создать двоичное дерево поиска. Небольшая проблема заключается в том, что наши вспомогательные функции не являются частью класса заголовка, и поэтому, когда я пытаюсь использовать вспомогательные функции, которые я создал, для добавления в дерево или для обхода дерева, это всегда приводит к ошибке сегментации или неправильному вывод. Код для класса заголовка просто создает класс структуры для узлов

struct MovieNode{
    int ranking;
    string title;
    int year;
    float rating;

    MovieNode* left = NULL;
    MovieNode* right = NULL;

    MovieNode(int rank, string t, int y, float r) {
        title = t;
        ranking = rank;
        year = y;
        rating = r;
    }
};

Файл исходного кода содержит все классы из файла заголовка, а также вспомогательные функции, которые я создал для того, чтобы помочь с заданием.

#include "MovieTree.hpp"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>

using namespace std;

// MovieNode: node struct that will be stored in the MovieTree BST

MovieTree::MovieTree() {
  this -> root = NULL;
}

MovieTree::~MovieTree() {
  // delete every node and then set the root to NULL
}

Я лично не знаю, как работают деструкторы. Мои всегда получают ошибки сегментации.

// helper function to printMovieInventory()
void inorderTraverse(MovieNode* node) {
  inorderTraverse(node -> left);
  cout << "Movie: " << node -> title << " " << node -> rating << endl;
  inorderTraverse(node -> right);
}

void MovieTree::printMovieInventory() {
   // using inorder traversal

   if (root == NULL) {
     cout << "Tree is Empty. Cannot print" << endl;
   }
   else if (root != NULL) {
     inorderTraverse(root);
   }
}

Эта функция используется для обхода заказа, чтобы распечатать все фильмы вместе с их рейтингом. На самом деле происходит ошибка сегментации.

// helper function to addMovieNode()
void insert(MovieNode* root, int ranking, string title, int year, float rating) {
  if (root == NULL) {
    root = new MovieNode(ranking, title, year, rating);
  }
  if (title < root -> title) {
    insert(root -> left, ranking, title, year, rating);
  }
  else if (title > root -> title) {
    insert(root -> right, ranking, title, year, rating);
  }
}

void MovieTree::addMovieNode(int ranking, string title, int year, float rating) {
  if (root == NULL) {
    root = new MovieNode(ranking, title, year, rating);
  }
  else if (root != NULL) {
    insert(root, ranking, title, year, rating);
  }
}

Эта функция меня смутила больше всего. Большинство функций, которые я видел, чтобы вставить новый узел в дерево, требуют указателя на узел Node* node и затем данных, которые будут go в узел. Поэтому, когда я запускаю эту функцию, она вставляет только первый узел (root), а затем в дерево ничего не вставляется.

// helper function to findMovie()
MovieNode* compare(string title, MovieNode* root) {
  if (root == NULL) {
    return NULL;
  }
  else {
    if (title.compare(root -> title) < 0) {
      compare(title, root -> left);
    }
    else if (title.compare(root -> title) > 0) {
      compare(title, root -> right);
    }
    else if (title.compare(root -> title) == 0) {
      return root;
    }
  }
}

void MovieTree::findMovie(string title) {
  if (root == NULL) {
    cout << "Movie not found." << endl;
  }
  else {
    MovieNode* foundMovie = compare(title, root);

    if (foundMovie == NULL) {
      cout << "Movie not found." << endl;
    }
    else {
      cout << "Movie Info:" << endl;
      cout << "==================" << endl;
      cout << "Ranking:" << foundMovie -> ranking << endl;
      cout << "Title  :" << foundMovie -> title << endl;
      cout << "Year   :" << foundMovie -> year << endl;
      cout << "rating :" << foundMovie -> rating << endl;
    }
  }
}

Эта функция сравнивает названия фильмов, а затем Обход дерева, чтобы найти mov ie, который соответствует ему. Если его нет в дереве, то возвращается, что mov ie не может быть найден. Этот выводит странные значения в рейтинге, году и рейтинге. Даже если mov ie не найден, он выводит для него некоторые случайные значения.

// helper functino to queryMovies()
void preorderTraverse(MovieNode* node, int rating, int year) {
  if (node -> rating >= rating && node -> year < year) {
    cout << node -> title << "(" << node -> year << ") " << node -> rating << endl;
  }
  else {
    preorderTraverse(node -> left, rating, year);
    preorderTraverse(node -> right, rating, year);
  }
}

void MovieTree::queryMovies(float rating, int year) {
  if (root == NULL) {
    cout << "Tree is Empty. Cannot query Movies" << endl;
  }
  else if (root != NULL) {
    cout << "Movies that came out after " << year << " with rating at least " << rating << endl;
    preorderTraverse(root, rating, year);
  }
}

Эта функция аналогична findMovie(), за исключением того, что сравнивает год и рейтинг, а затем распечатывает все фильмы, вышедшие после года и имеющие рейтинг, превышающий или равный рейтингу. Это происходит не в определенном порядке, поэтому я прошел по дереву, используя предварительный порядок. Он также получает ошибку сегментации.

// helper function to averageRating()
int average(MovieNode* node, int sum) {
  sum += node -> rating;

  average(node -> left, sum);
  average(node -> right, sum);


  return sum;
}

void MovieTree::averageRating() {
  if (root == NULL) {
    cout << "Average rating:0.0" << endl;
  }
  else if (root != NULL) {
    int avg = 0;
    avg += average(root, avg);

    cout << "Average rating:" << avg << endl;
  }
}

Как видно из названия, эта функция суммирует все оценки и делит на количество узлов, чтобы получить среднее значение. Над этим я все еще работаю, так что я знаю, что он полон ошибок.

// helper function to printLevelNodes()
void getLevel(MovieNode* node, int level) {
  if (node != NULL) {
    if (level == 0) {
      cout << "Movie: " << node -> title << " " << node -> rating << endl;
    }
    else if (level != 0) {
      getLevel(node -> left, level - 1);
      getLevel(node -> right, level - 1);
    }
  }

}

// helper function to printLevelNodes()
int maxLevel(MovieNode* node) {
  if (node == NULL) {
    return 0;
  }
  else {
    int leftD = maxLevel(node -> left);
    int rightD = maxLevel(node -> right);

    if (leftD > rightD) {
      return (leftD + 1);
    }
    else {
      return (rightD + 1);
    }

  }
}

void MovieTree::printLevelNodes(int level) {
  int max = maxLevel(root);

  if (level <= max) {
    getLevel(root, level);
  }
}

Забавно, последняя функция - единственная, которая работает. Это не имеет смысла для меня, потому что я моделировал вспомогательные функции друг за другом, но некоторые из них просто не работают. Есть ли способ получить доступ к дереву из вспомогательных функций, даже если они не являются частью файла заголовка? Если нет, то как работают некоторые вспомогательные функции, а другие нет?

1 Ответ

0 голосов
/ 04 марта 2020

Есть некоторые глупые ошибки в функции заказа , за которыми следует вставка функции . :( Следуйте за мной здесь:

Эта функция используется для обхода заказа, чтобы распечатать все фильмы вместе с их рейтингом. На самом деле происходит ошибка сегментации.

Причиной ошибки сегментации является то, что вы проверяете левую и правую части , даже если она содержит NULL . Где, вы должны проверять только левую часть, когда левая часть существует на самом деле, и она одинакова и для правой части.

изменить:

void inorderTraverse(MovieNode* node) {
 if(node -> left)
    inorderTraverse(node -> left);

 cout << "Movie: " << node -> title << " " << node -> rating << endl;

 if(node -> right)
    inorderTraverse(node -> right);
}

Эта функция меня смутила больше всего. Большинство функций, которые я видел, чтобы вставить новый узел в дерево, требуют указателя на узел Узел * узел, а затем данные, которые будут go в узел. Поэтому, когда я запускаю эту функцию, он вставляет только первый узел (root), а затем ничего больше не вставляется в дерево.

Поскольку вы хотите добавить узлы в точной позиции, сначала вам нужно go к этой позиции, затем только вы можете добавить узлы [или ссылку в правильной позиции].

изменить: * 10 24 *

MovieNode * insert(MovieNode* root, int ranking, string title, int year, float rating) 
{
 if (root == NULL) {
   return new MovieNode(ranking, title, year, rating);
 }
 if (title < root -> title) {
  root->left = insert(root -> left, ranking, title, year, rating);
 }
 else if (title > root -> title) {
   root-> right = insert(root -> right, ranking, title, year, rating);
 }

 return root;
}

void MovieTree::addMovieNode(int ranking, string title, int year, float rating) {
  if (root == NULL) {
    root = new MovieNode(ranking, title, year, rating);
  }
  else if (root != NULL) {
    root = insert(root, ranking, title, year, rating);
  }
}

СЕЙЧАС, надеюсь, все в порядке! Пинг здесь, если вы застряли или получили неправильный вывод в любом месте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...