簡體   English   中英

二叉搜索樹--插入節點

[英]Binary Search Tree--Inserting a Node

我正在嘗試實現 function 以將節點插入二叉搜索樹。 我正在使用以下代碼,但是當我嘗試打印到屏幕時,我看到的只是“root =1”。 關於我做錯了什么的任何建議?

#include <iostream>

class BTNode {
public:
   int item;
   BTNode *left;
   BTNode *right;
   BTNode(int i, BTNode *l=nullptr, BTNode *r=nullptr):item(i),left(l),right(r){}
};

BTNode *root = nullptr;
void insert(int i) {
   if (root==nullptr)
      root=new BTNode(i);
   else if(i<root->item){
      root=root->left;
      insert(i);
   }
   else{
      root=root->right;
      insert(i);
   }
}

int main()
{
   insert (5);
   insert (10);
   insert (1);
   
   if (root) 
   {
      std::cout << "root = " << root->item << std::endl;
      if (root->left)
         std::cout << "root->left = " << root->left->item << std::endl;
      if (root->right)
         std::cout << "root->right = " << root->right->item << std::endl;
   }
   
   return 0;
}

你的代碼效果如下

  1. insert(5):創建一個值為 5 的新 BTNode 並將其分配給 root
  2. insert(10):創建一個值為 10 的新 BTNode 並將其分配給 root。 您不再有對先前創建的節點的引用
  3. insert(1):新建一個值為1的BTNode,賦值給root。 您不再引用之前創建的兩個節點中的任何一個。

您可以通過這種方式實現插入 function,它通常是 BTNode class 的成員 function,這就是為什么我將它們稱為私有/公共,但由於您選擇將它們實現為 function 在 class 之外,我將保持這種方式。

首先你有一個公共插入 function

void insert(int i){
      insert( i,root);// call the private function. see below
}

其次你有一個私有插入 function (注意指針變量應該通過引用傳遞,否則它會改變指針的副本)

void insert(int i,BTNode *& t){
    if(t==nullptr)t=new Node(i);
    else if(i<t->item)insert(i,t->left);
    else insert(i,t->right);
}

我在下面寫下了代碼。

BTNode *root = nullptr;
BTNode* insert_node(int ivalue, BTNode* _parent) {
    if (_parent == nullptr) {
        return _parent = new BTNode(ivalue);
    }
    else if (ivalue<_parent->item) {
        _parent->left = insert_node(ivalue, _parent->left);
    }
    else {
        _parent->right = insert_node(ivalue, _parent->right);
    }
    return nullptr;
}
void insert(int i) {
    BTNode*newnode = insert_node(i, root);
    if (newnode)root = newnode;
}

int main()
{
    insert(5);
    insert(10);
    insert(1);
    //insert(2);
    //insert(4);
    if (root)
    {
        std::cout << "root = " << root->item << std::endl;
        if (root->left)
            std::cout << "root->left = " << root->left->item << std::endl;
        if (root->right)
            std::cout << "root->right = " << root->right->item << std::endl;
    }

    return 0;
}

您的insert function 正確地將新節點添加到樹中。 然而,作為一個副作用,它有時會改變全局變量root以指向根的左節點或右節點,這樣樹的 rest 就會丟失。 你的insert function 不應該改變根,除非root == nullptr

因此,我建議您重寫 function insert ,使其根本不使用root ,而是接收指向該節點的指針作為 function 參數。 該指針必須通過引用傳遞,而不是值傳遞,因為 function insert必須能夠更改傳遞的實際指針,如果它是nullptr的話。 為了實現這一點,您可以將 function 原型更改為以下內容:

void insert( BTNode &*pp_node, int i );

這也將使您的遞歸 function 調用正常工作,因為 function 現在可以像這樣重寫:

void insert( BTNode *&node, int i )
{
    if ( node == nullptr )
        node = new BTNode( i );
    else if ( i < node->item )
        insert( node->left, i );
    else
        insert( node->right, i );
}

您的 function main必須這樣重寫:

int main()
{
    insert( root, 5 );
    insert( root, 10 );
    insert( root, 1 );

    [...]
}

但是,由於您不再需要將root作為全局變量(因為它現在作為 function 參數傳遞),最好將其聲明為局部變量,如下所示:

int main()
{
    BTNode *root = nullptr;

    insert( root, 5 );
    insert( root, 10 );
    insert( root, 1 );

    [...]
}

雖然這個問題的遞歸解決方案有效,但迭代解決方案會更有效。 因此,您可能希望像這樣重寫 function insert

void insert( BTNode **pp_node, int i )
{
    while ( *pp_node != nullptr )
    {
        if ( i < (*pp_node)->item )
            pp_node = &(*pp_node)->left;
        else
            pp_node = &(*pp_node)->right;
    }

    *pp_node = new BTNode( i );
}

該解決方案需要指向指針的指針(所謂的雙指針)而不是指向指針的引用,因為不能重新分配引用。

但是,由於insert的 function 原型現在已經改變,您還必須相應地調整 function main

int main()
{
    BTNode *root = nullptr;

    insert( &root, 5 );
    insert( &root, 10 );
    insert( &root, 1 );

    [...]
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM