为什么析构函数会删除我原来的二叉搜索树?

时间:2016-11-12 19:21:48

标签: c++ templates binary-search-tree destructor deep-copy

所以我有一个项目,我必须为用户创建一个测试模式,检查我的复制构造函数和二进制搜索树的析构函数。我通过将二进制搜索树按值传递给类似testAdds的函数来执行此操作,该函数在内部调用复制构造函数,并在函数返回后隐式调用析构函数,从而确保它们都能正常工作。我遇到的问题是,在函数返回后调用析构函数时,它最终会删除我原来的二进制搜索树。我不知道为什么会发生这种情况,即使我按值而不是通过引用传递它。有人可以帮我理解为什么会发生这种情况以及如何解决这个问题?任何和所有的帮助表示赞赏! 这是我的代码:

//Executive is the class where I call the test methods (in switch case 6)

#include<fstream>
#include "Executive.h"

Executive::Executive(char* filename) : choice(0), cont(true)
{

    copycheck = false;
    file = filename;
    in.open(file);
    string line;
    while(getline(in, line))
    {
        string a;
        string j;
        string p;
        int i=0;
        for(char&c : line)
        {
            if(c==',') i++;
            else if(c==' ') continue;
            else if(i==0) a += c;
            else if(i==1) p += c;
            else if(i==2) j += c; 
        }
        Pokemon p1(a, stoi(p), j);
        if(!bst.add(p1))
        {
            cout<<"Could not add "<<a<<endl;
        }
    }

}

ofstream out;
void write(Pokemon& p)
{
    out<<p.getAname()<<","<<p.getPokenum()<<","<<p.getJname()<<endl;
}


void Executive::run()
{
    try
    {
        while(cont)
        {
            cout<<"What do you want to do with the Pokedex?"<<endl;
            cout<<"1) Search"<<endl;
            cout<<"2) Save"<<endl;
            cout<<"3) Copy"<<endl;
            cout<<"4) Add"<<endl;
            cout<<"5) Remove"<<endl;
            cout<<"6) Test"<<endl;
            cout<<"7) Quit"<<endl;

            cin>>choice;
            while(choice<1 || choice>7)
            {
                cout<<"Invalid choice. Try again"<<endl;
                cin>>choice;
            }

            switch(choice)
            {
                case 1:
                {
                    string name;
                    cout<<"\nEnter the Pokemon's American name: ";
                    cin>>name;

                    if(bst.contains(name))
                    {
                        Pokemon temp = bst.getEntry(name);
                        cout<<"Japanese Name: "<<temp.getJname()<<endl;
                        cout<<"Pokedex Number: "<<temp.getPokenum()<<'\n'<<endl;
                    }
                    else
                    {
                        cout<<name<<" is not in the pokedex\n"<<endl;
                    }
                    break;
                }
                case 2:
                {
                    string outfile;
                    string order;
                    if(copycheck)
                    {
                        cout<<"\nWhich pokedex do you want to save?"<<endl;
                        cout<<"1) Original"<<endl;
                        cout<<"2) Copy"<<endl;
                        cin>>choice;
                        while(choice<1 || choice>2)
                        {
                            cout<<"Invalid choice. Try again"<<endl;
                            cin>>choice;
                        }
                    }
                    else choice=1;
                    cout<<"Enter name for output file: ";
                    cin>>outfile;
                    out.open(outfile);
                    cout<<"Enter order of traversal:"<<endl;
                    cout<<"1) pre"<<endl;
                    cout<<"2) in"<<endl;
                    cout<<"3) post"<<endl;
                    int ochoice;
                    cin>>ochoice;
                    while(ochoice<1 || ochoice>3)
                    {
                        cout<<"Invalid choice. Try again"<<endl;
                        cin>>ochoice;
                    }
                    if(ochoice==1)
                    {
                        if(choice==1) bst.preorderTraverse(write);
                        else bstcopy.inorderTraverse(write);
                    }
                    else if(ochoice==2)
                    {
                        if(choice==1) bst.inorderTraverse(write);
                        else bstcopy.inorderTraverse(write);
                    }
                    else
                    {
                        if(choice==1) bst.postorderTraverse(write);
                        else bstcopy.postorderTraverse(write);
                    }
                    out.close();
                    cout<<"An output file with the name "<<outfile<<" has been created!\n"<<endl;
                    break;
                }
                case 3:
                {
                    bstcopy = bst;
                    copycheck = true;
                    cout<<"\nA copy of the pokedex has been created for editing\n"<<endl;
                    break;
                }
                case 4:
                {
                    if(copycheck)
                    {
                        string a, j;
                        int n;
                        cout<<"\nEnter pokemon's American name: ";
                        cin>>a;
                        a[0] = toupper(a[0]);
                        for(int i=1; i<a.length(); i++)
                        {
                            a[i] = tolower(a[i]);
                        }
                        cout<<"Enter pokemon's Japanese name: ";
                        cin>>j;
                        j[0] = toupper(j[0]);
                        for(int i=1; i<j.length(); i++)
                        {
                            j[i] = tolower(j[i]);
                        }
                        cout<<"Enter pokedex number: ";
                        cin>>n;
                        Pokemon p1(a, n, j);
                        if(!bstcopy.add(p1))
                        {
                            cout<<"Could not add "<<a<<'\n'<<endl;
                        }
                        else
                        {
                            cout<<a<<" has been successfully added to the pokedex\n"<<endl;
                        }
                    }
                    else
                    {
                        cout<<"\nYou need to create a copy before editing the pokedex!\n"<<endl;
                    }
                    break;
                }
                case 5:
                {
                    if(copycheck)
                    {
                        string a;
                        cout<<"\nEnter pokemon's American name: ";
                        cin>>a;
                        if(bstcopy.remove(a))
                        {
                            cout<<a<<" was successfully removed from the pokedex\n"<<endl;
                        }
                        else
                        {
                            cout<<a<<" is not in the pokedex!\n"<<endl;
                        }
                    }
                    else
                    {
                        cout<<"\nYou need to create a copy before editing the pokedex!\n"<<endl;
                    }
                    break;
                }
                case 6:
                {
                    cout<<"\nWhich test would you like to run?"<<endl;
                    cout<<"1) Test adding to a deep copy"<<endl;
                    cout<<"2) Test removing from a deep copy"<<endl;
                    cout<<"3) Test writing to file from a deep copy"<<endl;
                    cin>>choice;
                    while(choice<1 || choice>3)
                    {
                        cout<<"Invalid choice. Try again"<<endl;
                        cin>>choice;
                    }
                    if(choice == 1) t.testAdds(bst);
                    else if(choice == 2) t.testRemoves(bst);
                    else t.testWriteToFile(bst);
                    cout<<endl;
                    break;
                }
                default:
                    cont = false;
            }

        }
        cout<<"\nThanks for using the Pokedex!\n"<<endl;
    }
    catch(NotFoundException& e)
    {
        cout<<e.what()<<endl;
    }
}

//Test is the class where the test methods are defined

#include "Test.h"

ofstream fout;

void writetofile(Pokemon& p)
{
    fout<<p.getAname()<<","<<p.getPokenum()<<","<<p.getJname()<<endl;
}

void display(Pokemon& p)
{
    cout<<p.getAname()<<","<<p.getPokenum()<<","<<p.getJname()<<endl;
}

void Test::testAdds(BinarySearchTree<Pokemon, string> bstc)
{
    string a, j;
    int n;
    cout<<"Enter pokemon's American name: ";
    cin>>a;
    a[0] = toupper(a[0]);
    for(int i=1; i<a.length(); i++)
    {
        a[i] = tolower(a[i]);
    }
    cout<<"Enter pokemon's Japanese name: ";
    cin>>j;
    j[0] = toupper(j[0]);
    for(int i=1; i<j.length(); i++)
    {
        j[i] = tolower(j[i]);
    }
    cout<<"Enter pokedex number: ";
    cin>>n;
    Pokemon p1(a, n, j);
    if(!bstc.add(p1))
    {
        cout<<"Could not add "<<a<<endl;
    }
    else
    {
        bstc.inorderTraverse(display);
    }
    //bst.~BinarySearchTree();
}

void Test::testRemoves(BinarySearchTree<Pokemon, string> bstc)
{
    string a;
    cout<<"Enter pokemon's American name: ";
    cin>>a;
    if(bstc.remove(a))
    {
        bstc.inorderTraverse(display);
    }
    else
    {
        cout<<a<<" is not in the pokedex!"<<endl;
    }
    //bst.~BinarySearchTree();
}

void Test::testWriteToFile(BinarySearchTree<Pokemon, string> bstc)
{
    string outfile;
    cout<<"Enter name for output file: ";
    cin>>outfile;
    fout.open(outfile);
    bstc.inorderTraverse(writetofile);
    fout.close();
    cout<<"An output file with the name "<<outfile<<" has been created!"<<endl;
    //bst.~BinarySearchTree();
}

//Here's my Binary Search Tree file. I implement the copy constructor using a private recursive function called "copy" and overlaoding the = operator

//  Subsetted from:
//  Created by Frank M. Carrano and Tim Henry.
//  Copyright (c) 2013 __Pearson Education__. All rights reserved.

/** @file BinarySearchTree.cpp */
#include <iostream>

#include "BinarySearchTree.h" 

// PRIVATE HELPER METHODS - IMPLEMENT THESE

template<typename ItemType, typename KeyType>
void BinarySearchTree<ItemType, KeyType>::destroyTree(BinaryNode<ItemType>* subTreePtr)
{
    if(subTreePtr != nullptr)
    {
        if(subTreePtr->getLeftChildPtr() != nullptr)
        {
            destroyTree(subTreePtr->getLeftChildPtr());
        }
        if(subTreePtr->getRightChildPtr() != nullptr)
        {
            destroyTree(subTreePtr->getRightChildPtr());
        }
        delete subTreePtr;
    }
}

template<typename ItemType, typename KeyType>
BinaryNode<ItemType>* BinarySearchTree<ItemType,KeyType>::insertInorder(BinaryNode<ItemType>* subTreePtr, BinaryNode<ItemType>* newNodePtr)
{
    if(newNodePtr->getItem() < subTreePtr->getItem())
    {
        if(subTreePtr->getLeftChildPtr() == nullptr)
        {
            subTreePtr->setLeftChildPtr(newNodePtr);
            return nullptr;
        }
        else
        {
            return insertInorder(subTreePtr->getLeftChildPtr(), newNodePtr);
        }
    }
    if(newNodePtr->getItem() > subTreePtr->getItem())
    {
        if(subTreePtr->getRightChildPtr() == nullptr)
        {
            subTreePtr->setRightChildPtr(newNodePtr);
            return nullptr;
        }
        else
        {
            return insertInorder(subTreePtr->getRightChildPtr(), newNodePtr);
        }
    }
    return newNodePtr;
}

template<typename ItemType, typename KeyType>
BinaryNode<ItemType>* BinarySearchTree<ItemType, KeyType>::findNode(BinaryNode<ItemType>* subTreePtr, const KeyType& target) const
{
    if(subTreePtr != nullptr)
    {
        if(subTreePtr->getItem() > target)
        {
            return findNode(subTreePtr->getLeftChildPtr(), target);
        }
        if(subTreePtr->getItem() < target)
        {
            return findNode(subTreePtr->getRightChildPtr(), target);
        }
        return subTreePtr;
    }
    return nullptr;
}

template<typename ItemType, typename KeyType>
BinaryNode<ItemType>* BinarySearchTree<ItemType, KeyType>::recRemove(BinaryNode<ItemType>* root, ItemType& itemkey)
{
    if(root == nullptr)
    {
        return nullptr;
    }
    else if(root->getItem()>itemkey)
    {
        root->setLeftChildPtr(recRemove(root->getLeftChildPtr(), itemkey));
    }
    else if(root->getItem()<itemkey)
    {
        root->setRightChildPtr(recRemove(root->getRightChildPtr(), itemkey));
    }
    else
    {
        if(root->isLeaf())
        {
            delete root;
        }
        else if(root->getLeftChildPtr() == nullptr)
        {
            BinaryNode<ItemType>* temp = root;
            root = root->getRightChildPtr();
            delete temp;
        }
        else if(root->getRightChildPtr() == nullptr)
        {
            BinaryNode<ItemType>* temp = root;
            root = root->getLeftChildPtr();
            delete temp;
        }
        else
        {
            BinaryNode<ItemType>* b = greatest(root->getLeftChildPtr());
            ItemType item = b->getItem();
            root->setItem(item);
            root->setLeftChildPtr(recRemove(root->getLeftChildPtr(), item));
        }
    }
    return root;
}

template<typename ItemType, typename KeyType>
void BinarySearchTree<ItemType, KeyType>::recPre(void visit(ItemType&), BinaryNode<ItemType>* subTreePtr) const
{
    if(subTreePtr != nullptr)
    {
        ItemType temp = subTreePtr->getItem();
        visit(temp);
        recPre(visit, subTreePtr->getLeftChildPtr());
        recPre(visit, subTreePtr->getRightChildPtr());
    }
}

template<typename ItemType, typename KeyType>
void BinarySearchTree<ItemType, KeyType>::recIn(void visit(ItemType&), BinaryNode<ItemType>* subTreePtr) const
{
    if(subTreePtr != nullptr)
    {
        recIn(visit, subTreePtr->getLeftChildPtr());
        ItemType temp = subTreePtr->getItem();
        visit(temp);
        recIn(visit, subTreePtr->getRightChildPtr());
    }
}

template<typename ItemType, typename KeyType>
void BinarySearchTree<ItemType, KeyType>::recPost(void visit(ItemType&), BinaryNode<ItemType>* subTreePtr) const
{
    if(subTreePtr != nullptr)
    {
        recPost(visit, subTreePtr->getLeftChildPtr());
        recPost(visit, subTreePtr->getRightChildPtr());
        ItemType temp = subTreePtr->getItem();
        visit(temp);
    }
}

template<typename ItemType, typename KeyType>
BinaryNode<ItemType>* BinarySearchTree<ItemType, KeyType>::copy(BinaryNode<ItemType>* optr)
{
    if(optr != nullptr)
    {
        BinaryNode<ItemType>* newNode = new BinaryNode<ItemType>(optr->getItem());
        newNode->setLeftChildPtr(copy(optr->getLeftChildPtr()));
        newNode->setRightChildPtr(copy(optr->getRightChildPtr()));
        return newNode;
    }
    return nullptr;
}

template<typename ItemType, typename KeyType>
BinaryNode<ItemType>* BinarySearchTree<ItemType, KeyType>::greatest(BinaryNode<ItemType>* ptr)
{
    if(ptr!=nullptr && ptr->getRightChildPtr()!=nullptr)
    {
        return greatest(ptr->getRightChildPtr());
    }
    if(ptr!=nullptr && ptr->getRightChildPtr()==nullptr)
    {
        return ptr;
    }
    return nullptr;
}

//////////////////////////////////////////////////////////////
//      PUBLIC METHODS BEGIN HERE
//////////////////////////////////////////////////////////////

template<typename ItemType, typename KeyType>
BinarySearchTree<ItemType, KeyType>::BinarySearchTree() : rootPtr(nullptr) 
{
}

template<typename ItemType, typename KeyType>
BinarySearchTree<ItemType, KeyType>::~BinarySearchTree()
{
   this->destroyTree(rootPtr); // Call inherited method
}  // end destructor


//////////////////////////////////////////////////////////////
//      Public BinaryTreeInterface Methods Section - IMPLEMENT THESE
//////////////////////////////////////////////////////////////

template<typename ItemType, typename KeyType>
void BinarySearchTree<ItemType, KeyType>::operator=(BinarySearchTree<ItemType, KeyType>& bst)
{
    this->rootPtr = copy(bst.rootPtr);
}

template<typename ItemType, typename KeyType>
bool BinarySearchTree<ItemType, KeyType>::add(const ItemType& newData)
{
    BinaryNode<ItemType>* newNode = new BinaryNode<ItemType>(newData);
    if(rootPtr == nullptr)
    {
        rootPtr = newNode;
        return true;
    }
    if(insertInorder(rootPtr, newNode) == nullptr)
    {
        return true;
    }
    return false;
}

template<typename ItemType, typename KeyType>
bool BinarySearchTree<ItemType, KeyType>::remove(const KeyType& key)
{
    if(contains(key))
    {
        KeyType a = key;
        ItemType item = getEntry(a);
        rootPtr = recRemove(rootPtr, item);
        return true;
    }
    return false;
}

template<typename ItemType, typename KeyType>
ItemType BinarySearchTree<ItemType, KeyType>::getEntry(const KeyType& aKey) const throw(NotFoundException)
{
    BinaryNode<ItemType>* entry = findNode(rootPtr, aKey);
    if(entry != nullptr)
    {
        return entry->getItem();
    }
    throw(NotFoundException("Node with given key doesn't exist"));
}

template<typename ItemType, typename KeyType>
bool BinarySearchTree<ItemType, KeyType>::contains(const KeyType& aKey) const
{
    BinaryNode<ItemType>* entry = findNode(rootPtr, aKey);
    if(entry != nullptr)
    {
        return true;
    }
    return false;
}

//////////////////////////////////////////////////////////////
//      Public Traversals Section - IMPLEMENT THESE
//////////////////////////////////////////////////////////////

template<typename ItemType, typename KeyType>
void BinarySearchTree<ItemType, KeyType>::preorderTraverse(void visit(ItemType&)) const
{
    recPre(visit, rootPtr);
}

template<typename ItemType, typename KeyType>
void BinarySearchTree<ItemType, KeyType>::inorderTraverse(void visit(ItemType&)) const
{
    recIn(visit, rootPtr);
}

template<typename ItemType, typename KeyType>
void BinarySearchTree<ItemType, KeyType>::postorderTraverse(void visit(ItemType&)) const
{
    recPost(visit, rootPtr);
}

0 个答案:

没有答案