[英]How can I debug my C++ Binary Search Tree?
I can't figure this out.我想不通。 My search tree only saves the first entry from the input list.我的搜索树只保存输入列表中的第一个条目。 I want to build pre, inline, and post traversals along with with some other functions (this will be done after I fix this mess).我想构建 pre、inline 和 post 遍历以及其他一些功能(这将在我修复这个混乱之后完成)。
There are many solutions, but I want to get better, so I want to know what is wrong with what I did.有很多解决方案,但我想变得更好,所以我想知道我所做的有什么问题。
BSNODE.H
#include <iostream>
#include <cstddef>
#ifndef BSNODE_H
#define BSNODE_H
template <typename T>
class BSNode
{
private:
T m_entry; // A data item
BSNode<T>* m_left; // Pointer to next node
BSNode<T>* m_right;
public:
BSNode();
BSNode(const T& entry);
BSNode(const T& entry, BSNode<T>* left, BSNode<T>* right);
void setEntry(const T& entry);
void setLeft(BSNode<T>* left);
void setRight(BSNode<T>* right);
T getEntry() const ;
BSNode<T>* getLeft() const ;
BSNode<T>* getRight() const ;
};
#include "BSNode.cpp"
#endif
BSNODE.CPP
#include "BSNode.h"
using namespace std;
/*Class member variables
char m_entry;
BSNode* m_next;*/
template <typename T>
BSNode<T>::BSNode() : m_left(nullptr), m_right(nullptr)
{
}
template <typename T>
BSNode<T>::BSNode(const T& entry) : m_entry(entry), m_left(nullptr), m_right(nullptr)
{
}
template <typename T>
BSNode<T>::BSNode(const T& entry, BSNode<T>* left, BSNode<T>* right): m_entry(entry), m_left(left), m_right(right)
{
}
template <typename T>
T BSNode<T>::getEntry() const{
return m_entry;
}
template <typename T>
void BSNode<T>::setEntry(const T& entry){
m_entry=entry;
}
template <typename T>
BSNode<T>* BSNode<T>::getLeft() const{
return m_left;
}
template <typename T>
void BSNode<T>::setLeft(BSNode<T>* left){
m_left=left;
}
template <typename T>
BSNode<T>* BSNode<T>::getRight() const{
return m_right;
}
template <typename T>
void BSNode<T>::setRight(BSNode<T>* right){
m_right=right;
}
BSTINTERFACE.H
#ifndef BSTINTERFACE_H
#define BSTINTERFACE_H
#include <iostream>
#include "BSNode.h"
using namespace std;
//ItemType: What is being stored in the tree?
//KeyType: What type is used to search for an Item?
template <typename ItemType, typename KeyType>
class BinarySearchTreeInterface
{
public:
virtual ~BinarySearchTreeInterface(){}
virtual void add(ItemType entry) = 0;
virtual ItemType search(KeyType key) const = 0;
virtual void clear() = 0;
//More methods to come in next lab
};
#endif
BST.H
#ifndef BST_H
#define BST_H
#include <iostream>
#include "BSTInterface.h"
#include <stdexcept>
template <typename ItemType, typename KeyType>
class BST : public BinarySearchTreeInterface<ItemType, KeyType>
{
public:
BST():m_root(nullptr){};
~BST(){};
virtual ItemType search(KeyType key) const;
virtual void add(ItemType entry);
virtual void clear();
private:
BSNode<ItemType>* m_root;
/**add function will take in Pokemon ID with m_root as subtree. Will make for checks to see if duplicates are made **/
void add(ItemType entry, BSNode<ItemType>* subtree);
/**search will traverse through the tree recursively using operator overloads and doing checks for a Pokemon object with an ID taken from user**/
ItemType search(KeyType key, BSNode<ItemType>* subtree) const;
/**clear will use recursive calls get subtree to where it needs to get to and with recursive mix calls of subtree->getLeft subtree->getRight with delete subtree, this will
* delete the tree**/
void clear(BSNode<ItemType>* subtree);
};
#include "BST.cpp"
#endif
BST.CPP
#include "BST.h"
using namespace std;
template <typename ItemType, typename KeyType>
void BST<ItemType,KeyType>::clear(){
clear(m_root);
}
template <typename ItemType, typename KeyType>
void BST<ItemType,KeyType>::clear(BSNode<ItemType>* subtree){
if(subtree->getLeft()!= nullptr){
clear(subtree->getLeft());
}
if(subtree->getRight()!=nullptr){
clear(subtree->getRight());
}
delete subtree;
}
//public add func
template <typename ItemType, typename KeyType>
void BST<ItemType,KeyType>::add(ItemType entry){
if(m_root == nullptr){
m_root= new BSNode<ItemType>(entry);
}
else{
add(entry, m_root);
}
}
//private add func
template <typename ItemType, typename KeyType>
void BST<ItemType,KeyType>::add(ItemType entry, BSNode<ItemType>* subtree){
if(subtree->getEntry() > entry.getID()){
if(subtree->getRight()!=nullptr){
add(entry,subtree->getRight());
}
else{
BSNode<ItemType>* n= new BSNode<ItemType>(entry);
subtree->setRight(n);
}
}
else if(subtree->getEntry() < entry.getID()){
if(subtree->getLeft()!=nullptr){
add(entry, subtree->getLeft());
}
else{
BSNode<ItemType>* n= new BSNode<ItemType>(entry);
subtree->setLeft(n);
}
}
else{
throw(std::runtime_error("There are duplicate pokemon in the file that were not added\n"));
}
}
//public search func
template <typename ItemType, typename KeyType>
ItemType BST<ItemType, KeyType>::search(KeyType key) const{
return(search(key, m_root));
}
//private search func
template<typename ItemType, typename KeyType>
ItemType BST<ItemType, KeyType>::search(KeyType key, BSNode<ItemType>* subtree) const {
//check for nullptr, check for empty
if(subtree==nullptr){
throw(std::runtime_error("Item not in tree\n"));
}
/*
below accesses entry in BSNode which in this case is Poke Object
and that is why the overload operator will take over and check if
m_id == key
*/
else if(subtree->getEntry() == key)
{
//remember that this returns the "ItemType",
//in this lab it returns a pokemon object.
return(subtree->getEntry());
}
else{
//check the rest of tree
//traverse down appropriate road
if(subtree->getEntry() > key){
return(search(key, subtree->getLeft()));
}
else{
return(search(key, subtree->getRight()));
}
}
}
POKEMON.H
#ifndef POKEMON_H
#define POKEMON_H
#include <string>
using namespace std;
class Pokemon
{
public:
Pokemon():US_name(""),m_id(0),JP_name(""){};
Pokemon(std::string name, int m_id, std::string jname);
/*
This is kept for notes, the issues with below is that Left Hand Side
is compared to Right Hand Side but the whole object is passed in to RHS,
it is much easier on the computer (takes less memory) to have a "KEY"
to pass along and compare each object KEY to. In this lab it is Poke ID number
*/
//bool operator==(const Pokemon& rhs) const;
//bool operator<(const Pokemon& rhs) const;
//bool operator>(const Pokemon& rhs) const;
bool operator==(int id) const;
bool operator<(int id) const;
bool operator>(int id) const;
string getUS(){return US_name;}
int getID(){return m_id;}
string getJP(){return JP_name;}
void setUS(string US){
US_name=US;
}
void setID(int id){
m_id=id;
}
void setJP(string JP){
JP_name=JP;
}
private:
//what data do Pokemon have?
//What are the related data?
std::string US_name;
int m_id;
std::string JP_name;
};
#endif
POKEMON.CPP
#include "Pokemon.h"
Pokemon::Pokemon(std::string name, int id, std::string jname)
{
US_name=name;
m_id = id;
JP_name=jname;
}
//bool Pokemon::operator==(const Pokemon& rhs) const
//{
//if they ids are the same, they're the same Pokemon
//return(m_id == rhs.m_id);
//}
bool Pokemon::operator==(int id) const
{
return(m_id == id);
}
bool Pokemon::operator<(int id) const
{
return(m_id < id);
}
bool Pokemon::operator>(int id) const
{
return(m_id > id);
}
EXECUTIVE.H
#ifndef EXECUTIVE_H
#define EXECUTIVE_H
#include <iostream>
#include <string>
#include <fstream>
#include "BST.h"
#include "Pokemon.h"
using namespace std;
class Executive{
private:
public:
/** These are to take in info from file **/
string tempUS;
int tempID;
string tempJP;
Executive(string filename);
~Executive(){
}
};
#endif
EXECUTIVE.CPP
#include "Executive.h"
using namespace std;
Executive::Executive(string filename){
ifstream fin;
fin.open(filename);
if(fin.fail()){
cout << "File not found";
}
else{
BST<Pokemon,int> Tree;
while(fin>> tempUS >> tempID >> tempJP){
Pokemon Poke;
Poke.setUS(tempUS);
Poke.setID(tempID);
Poke.setJP(tempJP);
try{
Tree.add(Poke);
}
catch(runtime_error& rte){
cout << rte.what() << endl;
}
}
int choice;
do{
cout << "Enter 0 to Exit\nEnter 1 to Add a pokemanz\nEnter 2 to Search for a pokemanz\n";
cin >> choice;
if(choice==1){
string tUS, tJP;
int tID;
cout << "US Name: ";
cin >> tUS;
cout << "ID: ";
cin >> tID;
cout << "JP Name: ";
cin >> tJP;
Pokemon Poke;
Poke.setUS(tUS);
Poke.setID(tID);
Poke.setJP(tJP);
try{
Tree.add(Poke);
}
catch(runtime_error& rte){
cout << rte.what() << endl;
}
}
if(choice==2){
int tID;
cout << "Enter Pokemon ID:";
cin >> tID;
try{
Pokemon Poke1 = (Tree.search(tID));
cout << "<" << Poke1.getUS() << ">" << " <" <<
Poke1.getID() << "> <" << Poke1.getJP() << ">\n";
cout << endl;
}
catch(runtime_error& rte){
cout << rte.what() << endl;
}
}
}while(choice!=0);
Tree.clear();
}
}
MAIN.CPP
#include <iostream>
#include "Executive.h"
using namespace std;
int main(int argc, char* argv[])
{
if(argc < 2)
{
cout << "Incorrect number of parameters!\n";
}
else
{
Executive exec(argv[1]);
}
return 0;
}
MAKEFILE
run: main.o Executive.o Pokemon.o
g++ -g -std=c++11 -g -Wall main.o Executive.o Pokemon.o -o run
main.o: main.cpp
g++ -g -std=c++11 -g -c -Wall main.cpp
Executive.o: Executive.h Executive.cpp BSTInterface.h BST.h BST.cpp BSNode.h BSNode.cpp
g++ -g -std=c++11 -g -c -Wall Executive.cpp
Pokemon.o: Pokemon.h Pokemon.cpp
g++ -g -std=c++11 -g -c -Wall Pokemon.cpp
clean:
rm *.o run
leak:
valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes ./run input.txt
INPUT.TXT
Abra 63 Casey
Aerodactyl 142 Ptera
Alakazam 65 Foodin
Arbok 24 Arbok
Arcanine 59 Windie
Articuno 144 Freezer
Beedrill 15 Spear
Bellsprout 69 Madatsubomi
Blastoise 9 Kamex
Bulbasaur 1 Fushigidane
In your node-adding function在您的节点中添加 function
if(subtree->getEntry() > entry.getID()){
if(subtree->getRight()!=nullptr){
add(entry,subtree->getRight());
}
else{
BSNode<ItemType>* n= new BSNode<ItemType>(entry);
subtree->setRight(n);
}
}
else if(subtree->getEntry() < entry.getID()){
if(subtree->getLeft()!=nullptr){
add(entry, subtree->getLeft());
}
else{
BSNode<ItemType>* n= new BSNode<ItemType>(entry);
subtree->setLeft(n);
}
}
The traverse go right when ID to add is smaller than current node's ID.当要添加的 ID 小于当前节点的 ID 时,向右遍历 go。
On the other hand, in your node-searching function另一方面,在您的节点搜索 function
if(subtree->getEntry() > key){
return(search(key, subtree->getLeft()));
}
else{
return(search(key, subtree->getRight()));
}
The traverse go left when ID to search is smaller than current node's ID.当要搜索的 ID 小于当前节点的 ID 时,遍历 go离开。
This mismatch is preventing IDs of nodes other than the root (1st on the list) node from being found.这种不匹配会阻止找到除根(列表中的第一个)节点以外的节点的 ID。
You have to invert either choice to solve this issue.您必须颠倒任一选择来解决此问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.