首页 > 解决方案 > 在二叉搜索树上没有得到输出,有什么方法可以帮助我找到我在 C++ 中的错误吗?

问题描述

我的地图.h

////////////
/* This is your h file. DO NOT edit it!
 *
 * TODO 1: implement the MyMap-related functions in MyMap.hpp
 * TODO 2: implement the get_letter_frequency() functionin MyMap.hpp
 * TODO 3: implement the get_identity function in MyMap.hpp
 * TODO 4: thoroughly test your MyMap class to ensure proper functional
    behaviors
*/

#ifndef MYMAP_H
#define MYMAP_H

#include <iostream>
#include <stdexcept>
#include <string>
#include <utility>
#include "Dictionary.h"
#include "TreeNode.h"

using std::cout;
using std::endl;
using std::cerr;
using std::cin;

/*
* Same as before
*/
void get_identity(std::string &my_id);


template <typename K, typename V>
class MyMap: public Dictionary<K, V>
{
    private:
        TreeNode<MyPair<K, V>> *root = nullptr;

        V & at_helper(TreeNode<MyPair<K, V>> *&rt, const K &key);

        int size_helper(TreeNode<MyPair<K, V>> *rt) const;

        void clear_helper(TreeNode<MyPair<K, V>> *&rt);

        void insert_helper(TreeNode<MyPair<K, V>> *&rt,
          const MyPair<K, V> &init_pair);

        TreeNode<MyPair<K, V>> * get_min(TreeNode<MyPair<K, V>> *rt);

        void erase_helper(TreeNode<MyPair<K, V>> *&rt, const K &key);

        MyPair<K, V> * find_helper(TreeNode<MyPair<K, V>> *rt,
          const K &key) const;

        void print_helper(TreeNode<MyPair<K, V>> *rt, std::string indent) const;

        int count_helper(TreeNode<MyPair<K, V>> *rt, const K &key) const;

        // This is a helper function for the copy constructor and operator=
        // It should recursively clone the whole tree, by using new to make a
        //  new tree node, whose left and right children are clones of the left
        //  and right children...
        // Take inspiration from the recursive "count" function presented in
        //  class for counting the number of nodes in a binary tree
        TreeNode<MyPair<K, V>> * clone(const TreeNode<MyPair<K, V>> *rt);

    public:
        MyMap();

        ~MyMap();

        MyMap(const MyMap<K, V> &source);

        MyMap<K, V> & operator=(const MyMap<K, V> &source);

        V & at(const K &key);

        V & operator[](const K &key);

        bool empty() const;

        int size() const;

        void clear();

        void insert(const MyPair<K, V> &init_pair);

        void erase(const K &key);

        MyPair<K, V> * find(const K &key) const;

        void print() const;

        int count(const K &key) const;
};

// Should accept a text file (for example a book) via std in (standard input),
//  for example: ./yourprogram < sample_input.txt
// Should build a dictionary of the counts of the characters in that file
// Do not add newlines (\n) to the dictionary (they'll mess up print, so ignore
//  them) 
void get_letter_frequency(MyMap<char, int> &in_tree);


#include "MyMap.hpp"
#endif

我的地图.hpp

 /* Define all your MyMap-related functions here, including the get_identity
    function
 * You do not need to include MyMap.h in this hpp header file. It includes
    this file at the bottom.
 */
 using namespace std;

 void get_identity(std::string &my_id)
 {
     my_id = "tjb994";
 }

 template <typename K, typename V>
 MyMap<K, V>::MyMap(){
    TreeNode<MyPair<K, V>> *root = nullptr;
    
 }

 template <typename K, typename V>
 MyMap<K, V>::~MyMap(){
    clear_helper(root);
 }

 template <typename K, typename V>
 MyMap<K, V>::MyMap(const MyMap<K, V> &source){
    if(source.root == NULL)
    {
        this->root = NULL;
    }
    else{
        this->root = clone(source.root);
    }
 }

 template <typename K, typename V>
 MyMap<K, V> & MyMap<K, V>::operator=(const MyMap<K, V> &source){

    clear();
    if(source.root == NULL)
    {
        this->root = NULL;
    }
    else{
        this->root = clone(source.root);
    }

    return *this;
 }

 template <typename K, typename V>
    V & MyMap<K, V>::at(const K &key){

        return at_helper(root, key);
        }

template <typename K, typename V>
V & MyMap<K, V>::operator[](const K &key){
    if(find_helper(root, key) == NULL)
    {
        MyPair<K, V> tempnode(key);
        insert_helper(root, tempnode);
        return at_helper(root, key); 
    }
    else
    {
        return at_helper(root, key);
    }
    }


template <typename K, typename V>
bool MyMap<K, V>::empty() const{

    if(size_helper(root) != 0)
    {
        return false;
    }
    else
    {
    return true;
    }
}

template <typename K, typename V>
int MyMap<K, V>::size() const{
    return size_helper(root);
}

template <typename K, typename V>
void MyMap<K, V>::clear(){
    clear_helper(root);
    root = NULL;
}

template <typename K, typename V>
void MyMap<K, V>::insert(const MyPair<K, V> &init_pair){
    insert_helper(root, init_pair);
        }


template <typename K, typename V>
void MyMap<K, V>::erase(const K &key){
    erase_helper(root, key);
}

template <typename K, typename V>
MyPair<K, V> * MyMap<K, V>::find(const K &key) const{

    MyPair<K, V> *tempPair = find_helper(root, key);

    if(tempPair != NULL){
        return tempPair;
    }

    else{
    throw std::out_of_range ("MyMap:at");
      }


}


template <typename K, typename V>
void MyMap<K, V>::print() const{

    print_helper(root, " ");
}

template <typename K, typename V>
int MyMap<K, V>::count(const K &key) const{
    return count_helper(root, key);
}


template <typename K, typename V>
V & MyMap<K, V>::at_helper(TreeNode<MyPair<K, V>> *&rt, const K &key)
{
    if(key < rt->data.first)
    {
        return at_helper(rt->left, key);
    }

  else if(key > rt->data.first){
    return at_helper(rt->right, key);
    }

  else if(key == rt->data.first)
  {
    return rt->data.second;
  }

  else
  {
    throw std::out_of_range ("MyMap:a");
  }

}

template <typename K, typename V>
int MyMap<K, V>::size_helper(TreeNode<MyPair<K, V>> *rt) const
{
    static int size = 0;
  //Count the number of elements. I chose to do this as a post order traversal
  if(rt == NULL)
    return 0;

  size += size_helper(rt->left);
  size += size_helper(rt->right);

  size++;

  return size;
}

template <typename K, typename V>
void MyMap<K, V>::clear_helper(TreeNode<MyPair<K, V>> *&rt)
{
    //Traverse the tree and delete the nodes post order.
  if(rt == NULL){
        return;
  }

  clear_helper(rt->left);
  clear_helper(rt->right);

  delete rt;
}

template <typename K, typename V>
void MyMap<K, V>::insert_helper(TreeNode<MyPair<K, V>> *&rt, const MyPair<K, V> &init_pair)
{
    if(rt == NULL)
    {
        rt = new TreeNode<MyPair<K,V>>(init_pair,NULL,NULL);
    }
    else if (rt->data.first > init_pair.first)
    {
        insert_helper(rt->left,init_pair);
    }
    else
    {
        insert_helper(rt->right,init_pair);
    }
}

template <typename K, typename V>
TreeNode<MyPair<K, V>> * MyMap<K, V>::get_min(TreeNode<MyPair<K, V>> *rt)
{
    if(rt->left == NULL)
    {
        return rt;
    }

     else{
        return get_min(rt->left);
      }

}

template <typename K, typename V>
void MyMap<K, V>::erase_helper(TreeNode<MyPair<K, V>> *&rt, const K &key)
{
    if(rt == NULL)
    {
        return;
    }


  if(key < rt->data.first)
  {
    erase_helper(rt->left, key);
  }

  else if(key > rt->data.first)
  {
    erase_helper(rt->right, key);
  }

  else{
    TreeNode<MyPair<K, V>> *temp_1 = rt;
    if(rt->left == NULL)
    {
              rt = rt->right;
    }

    else if(rt->right == NULL)
    {
     rt = rt->left;
    }

    else{
      TreeNode<MyPair<K, V>> *temp_2 = get_min(rt->right);
      rt->data.first = temp_2->data.first;
      rt->data.second = temp_2->data.second;

      //Find the minimum and keep note of it's parent node
      TreeNode<MyPair<K, V>> *iter = rt->right;
      while(iter->left!= NULL){
          if(iter->left->left != NULL){
            iter = iter->left;  
          }

      }

      if(rt->right == iter)
      {
        rt->right = iter->right;
      }

      else{
        if(temp_2->right != NULL)
        {
          iter->left = temp_2->right;           
        }

      }

      delete temp_2;
    }

    delete temp_1;
  }
}


template <typename K, typename V>
MyPair<K, V> * MyMap<K, V>::find_helper(TreeNode<MyPair<K, V>> *rt, const K &key) const
{
    if(rt == NULL)
    {
        return NULL;
    }


  if(key < rt->data.first)
  {
    return find_helper(rt->left, key);
  }

  else if(key > rt->data.first)
  {
    return find_helper(rt->right, key);
  }

  else
  {
    return &(rt->data);
  }

}

template <typename K, typename V>
void MyMap<K, V>::print_helper(TreeNode<MyPair<K, V>> *rt, std::string indent) const
{
    if(rt == NULL)
    {
        cout << indent << "[empty]" << endl;
        return;
    }
    else
    {
        print_helper(rt->right, indent);
        cout << rt->data.first << rt->data.second << endl;
        print_helper(rt->left, indent);
    }
}


template <typename K, typename V>
int MyMap<K, V>::count_helper(TreeNode<MyPair<K, V>> *rt, const K &key) const
{
    if(rt == NULL)
    return 0;

  if(key < rt->data.first)
  {
    return count_helper(rt->left, key);
  }

  else if(key > rt->data.first)
  {
    return count_helper(rt->right, key);
  }

  else
  {
        return 1;
  }

}

template <typename K, typename V>
TreeNode<MyPair<K, V>> * MyMap<K, V>::clone(const TreeNode<MyPair<K, V>> *rt)
{
    if(rt == NULL){
    return NULL;
    }

  MyPair<K, V> tempPair(rt->data.first, rt->data.second);
  TreeNode<MyPair<K, V>> * thisNode = new TreeNode<MyPair<K, V>>(tempPair, clone(rt->left), clone(rt->right));

  return thisNode;
}
//
//template <typename K, typename V>
//void get_letter_frequency(MyMap<char, int> &in_tree)
//{
//  std::string letter;
//  getline(cin, letter);
//  
//
//
//}

主程序:

#include "MyMap.h"

int main()
{
    
    MyMap<int, std::string> map_obj;

    map_obj.insert(MyPair<int, std::string>(3, "h"));
    map_obj[54].push_back('w');
    map_obj[34] = "x";
    map_obj[54] = "x";
    map_obj[154] = "p";
    map_obj[73] = "w";
    map_obj[5] = "a";
    map_obj[36] = "x";
    map_obj[32] = "x";
    map_obj[84] = "x";
    map_obj.at(34) = "y";
    

    const MyPair<int, std::string> *temp = map_obj.find(34);
    cout << temp->first << " " << temp->second << endl;

    map_obj.erase(34);
    cout << (map_obj.find(34) == nullptr) << endl;

    MyMap<int, std::string> map_obj2(map_obj);

    MyMap<int, std::string> map_obj3;
    map_obj3 = map_obj2 = map_obj;

    cout << "==== printing tree ====" << endl;

    map_obj2.print();

    cout << "==== done printing tree ====" << endl;

    cout << "Size is: " << map_obj2.size() << endl;
    cout << "Count for 32 is: " << map_obj2.count(32) << endl << endl;

    map_obj.clear();

    cout << "==== printing tree ====" << endl;
    map_obj.print();
    cout << "==== done printing tree ====" << endl;

    cout << "Size is: " << map_obj.size() << endl;
    cout << "Count for 57 is: " << map_obj.count(57) << endl;

    try
    {
        map_obj.at(34) = "k";
    }
    catch(const std::out_of_range &e)
    {
        cout << e.what();
    }

    //MyMap<char, int> new_tree;
    //get_letter_frequency(new_tree);             (commented out until function is complete)
   // new_tree.print();

    return 0;
}

字典.h

/* Abstract dictionary class to inherit when implementing your BST MyMap class
 * It uses the TreeNode class to contain a MyPair object as its data element
 * DO NOT edit this file.
 */

#ifndef DICTIONARY_H
#define DICTIONARY_H

#include "MyPair.h"

template <typename K, typename V>
class Dictionary
{
    public:
        // Should only update, but NOT insert
        // Should throw std::out_of_range exception
        virtual V & at(const K &key) = 0;

        // Updates or inserts
        virtual V & operator[](const K &key) = 0;

        virtual bool empty() const = 0;

        virtual int size() const = 0;

        virtual void clear() = 0;

        virtual void insert(const MyPair<K, V> &init_pair) = 0;

        // Removes by key
        virtual void erase(const K &key) = 0;

        // Not exactly like the std:: version, but similar.
        virtual MyPair<K, V> * find(const K &key) const = 0;

        // Not actually like the std:: version; backwards in order traversal
        //  print
        // See the print function example in class presentation
        virtual void print() const = 0;

        virtual int count(const K &key) const = 0;
};

#endif

我的配对.h

/* Declaration of MyPair, which resembles std::pair
 * Use this as the element to store in your TreeNode.
 * DO NOT edit this file.
 * After this assignment (e.g., pa07 and beyond) you can use std::pair
 * https://en.cppreference.com/w/cpp/utility/pair
 */

#ifndef MYPAIR_H
#define MYPAIR_H

template <typename K, typename V>
struct MyPair
{
    K first;
    V second;

    MyPair(){}
    MyPair(const K &key): first(key) {}
    MyPair(const K &key, const V &value): first(key), second(value) {}
};

#endif

树节点.h

/* Use it as the node in the BST MyMap
 * DO NOT edit this file.
 */

#ifndef TREENODE_H
#define TREENODE_H

template <typename T>
struct TreeNode
{
    T data;
    TreeNode *left;
    TreeNode *right;
    TreeNode(const T &x, TreeNode *lc, TreeNode *rc):data(x), left(lc),
      right(rc) {}
};

#endif

在我的主程序中,它会一直运行,直到出现 insert() 函数,然后它不再给出输出,只有黑屏,返回值为 3359359859,这表明我在 MyMap.hpp 中定义的函数之一出错. 几天来我一直在寻找错误,但我无法确定出了什么问题。有人能指出我正确的方向吗?我假设一个构造函数,operator[],或者我的 operator=( 函数中的错误可能是可能的。

标签: c++dictionarytreebinary-search-tree

解决方案


推荐阅读