【问题标题】:Binary tree: insert node algorithm二叉树:插入节点算法
【发布时间】:2013-05-31 17:14:53
【问题描述】:

我正在尝试实现一棵二叉树(如果它是通用二叉树或二叉搜索树则不重要),我在创建节点并将其链接到树的函数时遇到了一些问题。
这是我目前写的代码:

class BinaryTree {
    class Node {
        char data;

        Node* leftChild;
        Node* rightChild;

        Node(char d, Node* lc, Node* rc):
            data(d), leftChild(lc), rightChild(rc) {}
    } *head;
    int treeSize;
public:
    BinaryTree(): head(0), treeSize(0) {}

    // totally wrong code
    void createNode(char dat) {
        if (head->data < dat)
            head->leftChild = new Node(dat, 0, 0);
        if (head->rightChild == 0)
            head->rightChild = new Node(dat, 0, 0);
        if (head == 0) {
            head = new Node(dat, head, head);
        }
    }
};

好吧,我想用链表来实现二叉树,但在这种情况下,问题是head 指针将指向最后添加的节点之一,而不是根。以这种方式使用链表的另一个问题可能是找到要添加新节点的节点的空子节点。
有人可以帮助我,或许可以提出更好的方法来实现二叉树?

注意:我打算将这个类设为template,char 只是为了即时试用。

【问题讨论】:

  • 如果您的编译器支持任何 C++11,请使用 std::unique_ptr&lt;Node&gt; 来保存您的 Nodes 和代表所有权转移的函数参数,并在需要时随意使用 std::move转让所有权,并在您为其分配 new Node 时为 reset

标签: c++ binary-tree


【解决方案1】:

我认为你移动的方式正确,但没有完成。您的方法可能如下所示:

void addNode( char data ) {
    // when root is uninitialized
    if ( NULL == head ) {
        head = new Node( data, NULL, NULL );
    } else {
        Node *currentNode = head;
        // search for the place to insert the new value
        while ( true ) {
            if ( currentNode->data < data ) {
                // if the current node already has left child
                // so we concern it further
                if ( NULL != currentNode->leftChild ) {
                    currentNode = currentNode->leftChild;
                    continue;
                // if the current node has no left child
                // so we create it with the new value
                } else {
                    currentNode->leftChild = new Node( data, NULL, NULL );
                    return;
                }
            } else {
                // similarly for the value that should be inserted into
                // right subtree
                if ( NULL != currentNode->rightChild ) {
                    currentNode = currentNode->rightChild;
                    continue;
                } else {
                    currentNode->rightChild = new Node( data, NULL, NULL );
                    return;
                }
            }
        }
    }
}

【讨论】:

  • 这实现了一个二叉搜索树对吧?我看到您检查了数据以决定将节点放在哪里。此外,如果对您来说不乏味,您可以添加一些 cmets(例如在更嵌套的 if 中)吗?
  • 是的,这肯定需要 cmets。 @Overflowh:树需要一种方法来查找您要查找的数据,并且您没有通过索引查找的成员,但是您确实有通过二进制搜索查找的成员,所以是的,这个答案是二进制的搜索。我想我们可以在随机位置插入,但祝你再次找到数据好运。除非您有其他查找节点的方法?
  • @MooingDuck:我认为我可能需要一个函数来查找树中的节点,并且我想实现广度优先搜索算法(因为我会明确插入算法)。
  • @Overflowh:如果您要进行广度优先搜索...我认为您不知道为什么要首先制作二叉树。几乎没有理由有一个没有索引或排序的二叉树。
  • @Overflowh:刚刚添加了 cmets
【解决方案2】:

以下是我注意到的几件事:

  1. 应该先检查 head!=null,否则先检查 createNode() 会崩溃。所有其他分支都应该在“else”中。

  2. 你的最后一个(或者我应该说第一个)新节点(dat,head,head)应该是新节点(dat,0,0) 为了代码清晰和/或作为国际维护程序员感谢活动的一部分。

  3. 您可能想要增加 treeSize。

否则,您就在正确的轨道上。继续。

【讨论】:

  • #2 是错误的。这很奇怪,但因为它只有在head == 0 时才会到达那个分叉,然后new Node(dat, head, head new Node(dat, 0, 0)
  • @MooingDuck:好吧,对不起。我已经写过并删除了很多次。复制/粘贴了整个函数体,因此它非常混乱。
【解决方案3】:

我假设这是某种家庭作业,所以我认为强调基础知识并让您弄清楚其余部分很重要。由于它是任何遍历树的起点,除非您删除根节点,否则 Head 永远不应更改。任何遍历都应该由另一个 Node 对象完成,该对象可以(并且可能经常会)在每个函数调用结束时超出范围,而不会对程序产生任何副作用。

正如已经指出的,您需要考虑 head = NULL 作为第一个条件的情况,然后处理 head != NULL 的后续遍历。对于插入,您必须考虑如何进行插入,并正确链接到树的其他元素。记住叶子是左右数据成员为 NULL 的任何 Node 对象可能会有所帮助。

祝你的程序好运。

【讨论】:

  • 所以,我应该这样修改:struct Node { /* stuff */ } *root, *traversal;?对我来说,一个名为 head (或 root)的对象在树的“填充”期间发生了变化,这对我来说似乎很奇怪。所以,我的 createNode 函数应该只在 == 0 时更改 *head ,而是改为*traversal 在其他情况下?
猜你喜欢
  • 1970-01-01
  • 2022-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多