将对象(数据包)插入二叉搜索树有什么好的方法?

时间:2019-06-20 21:24:07

标签: c++ binary-search-tree

我正尝试在此二进制搜索树中插入Packet object。但是问题是,我真的不知道这样做的好方法或如何去做。我正在寻找正确方向的一些指针,并向他们展示如何解决这个问题。

  • 忽略我对命名空间std的使用;因为这是为了教育 目的,而且我并不愿意(到目前为止)寻求进一步的发展!
  • 请帮助我解决我的具体问题,并尽可能告诉我如何 可以解决这个问题。

<< 看看我的代码 >>

Main.cpp:

#include <iostream>

#include "BST.h"
#include "Packet.h"

// IGNORE the USAGE of namespace std. as this is purely a testing program for educational purposes.
// It is NOT implementation for a real program.
using namespace std;

int main() {
    cout << "-------------------------------------------------------" << endl;
    cout << "Testing BST" << endl;
    cout << "-------------------------------------------------------" << endl;
    BST test1;
    Packet packetTest(123, "This is a packet of cheese.", 12.95, 10);
    // test1.insert(How should I choose to insert Packet? That's the question.);
    system("pause");
}

BST.h:

#pragma once

#include "Packet.h"

using namespace std;

class BST {
    struct Node {
        Node() : rlink(nullptr), llink(nullptr) {};
        ~Node() {};

        // Store packet here (for instance Packet *data or something)...
        Node *rlink, *llink;
    };
    public:
        BST();
        // void insert(How should I choose to insert Packet? That's the question.);
        void insert(Node *&p, Node *newNode);
        void preorderTraversal() const;
        void destroyTree();
        ~BST();
    private:
        Node * root;
        void destroyTree(Node *&p);
        void preorderTraversal(const Node *p) const;
};

BST.cpp (需要指导,请参见下面的代码,以了解我的意思)

#include "BST.h"
#include <iostream>

BST::BST() : root(nullptr) {}

// Need guidance here. What should I do for this function? How can I insert this object called Packet into the BST? 
/*void BST::insert(How should I choose to insert Packet? That's the question.) {
    Node *newNode = new Node;
    ...
    insert(root, newNode);
}*/

void BST::insert(Node *&p, Node *newNode) {
    if (p == nullptr) {
        p = newNode;
    }/*else if (p's data's getPartId() > newNode's data's getPartId()){
        insert(p->llink, newNode);
    }*/else {
        insert(p->rlink, newNode);
    }
}

void BST::preorderTraversal() const {
    if (root == nullptr) {
        cerr << "There is no tree.";
    }
    else {
        preorderTraversal(root);
    }
}

void BST::preorderTraversal(const Node *p) const {
    if (p != nullptr) {
        // cout << p->data->getPartId() << " "; Need to handle Packet's data here. But we need to implement Packet insection first!
        preorderTraversal(p->llink);
        preorderTraversal(p->rlink);
    }
}

void BST::destroyTree(Node *&p) {
    if (p != nullptr) {
        destroyTree(p->llink);
        destroyTree(p->rlink);
        delete p;
        p = nullptr;
    }
}

void BST::destroyTree() {
    destroyTree(root);
}

BST::~BST() {
    destroyTree(root);
}

Packet.h:

#pragma once
#include <string>

using namespace std;

class Packet {
public:
    Packet(int partId, string description, double price, int partCount) :
        partId(partId), description(description), price(price), partCount(partCount) {}
    int getPartId() const { return partId; }

private:
    int partId;
    string description;
    double price;
    int partCount;
};

这是我以前在BST.cpp中插入的实现:

void BST::insert(Packet &data) {
    Node *newNode = new Node;
    newNode->data = &data;
    insert(root, newNode);
}

如您所见,我不认为这是理想的。我的意思是我不得不两次使用&引用。有没有更优雅的解决方案,我可以在这方面得到指导吗?

1 个答案:

答案 0 :(得分:0)

问:如何将名为Packet的对象插入BST?

A:要在BST和Packet类之间创建一种关系,必须以某种方式定义一个。最佳实践要求建立一种关联,该关联在相关类之间施加最少的耦合。

我已在我认为最合适的位置在您的解决方案中实现了关联。 BST类的struct Node的rlink和llink指针。

// Store packet here (for instance Packet *data or something)... Packet* rlink, * llink;

关系是您将能够从Node或BST对象访问getPartId()的唯一方法。尽管Packet类不管理任何资源,因此不需要内存管理,但是关联只是类之间松散耦合关系的一个花哨的词,在这里就是这种情况。

void BST::insert(Node *&p, Node *newNode)中一样,递归调用函数时要小心。您不应该在没有退出条件的情况下递归地调用函数,并且永远不要真正使用递归,除非必须这样做,因为迭代是节省堆栈内存的一种选择。我发现您的插入函数中不需要递归,因此将其取出。我希望我替换它们对您有帮助:

void BST::insert(Packet& p) {
    Packet* newPacket = new Packet(p);
    insert(root, newPacket);
}

void BST::insert(Node*& p, Packet* newPacket) {
    if (p == nullptr) {
        p = new Node;
        p->llink = newPacket;
    }else if ((p->llink->getPartId()) > newPacket->getPartId()){
        p->llink = newPacket;
    }else {
        p->rlink = newPacket;
    }
}

然后我继续说:

void BST::preorderTraversal(const Node* p) const {
    if (p != nullptr) {
        cout << p->llink->getPartId() << " \n";
    }
}

void BST::destroyTree(Node*& p) {
    if (p != nullptr) {
        delete p;
        p = nullptr;
    }
}

就像我说的那样,关系是您将能够从Node或BST对象访问getPartId()的唯一方法。

关于评论,我同意。封装要求将所有数据成员保持私有状态,并且仅在必要时公开方法。我的解决方案允许您保留该功能

私人:void insert(Node*& p, Packet* newPacket);

您已经通过使preorderTraversal()重载使Node完全隐藏了。

干得好,希望我能帮上忙!