【问题标题】:Trying to recursively move through binary search tree to add a node尝试通过二叉搜索树递归移动以添加节点
【发布时间】:2016-07-31 16:58:39
【问题描述】:

我知道要通过 BST,您需要递归执行。就像一直向左移动然后返回轨道然后一直向右移动。我正在尝试添加一个节点,但语法让我感到困惑,因为我知道 addTreeNode 需要一个双指针,但是当我在递归调用它然后说“节点”不是结构或联合的一部分。我只是对如何管理这些结构有点困惑。

#include <stdio.h>
#include <stdlib.h>
#define ADD_LENGTH 30

typedef struct treeType{
    int listingId, price, propertySize;
    int numOfBeds, yearBuilt;
    double numOfBaths;
    char agent[20];
    char address[ADD_LENGTH];
    struct treeType *left;
    struct treeType *right;

}bNode;

typedef struct treeFrame{
    bNode *node;

}bTree;

void init(bTree **tree);
void addTreeNode(bTree **tree, bNode *temp);



int main(void)
{
    bTree *tree;
    int numOfProperties;
    int i;

    init(&tree);
    FILE *fp;
    fp = fopen("library.txt","r");
    if(fp == NULL){
        printf("fopen failed\n");
    }
    fscanf(fp, "%d", &numOfProperties);
    printf("%d\n", numOfProperties);
    bNode temp;
  //  for(i = 0; i < numOfProperties; i++){
    fscanf(fp,"%d %s %d %d %d %lf %d %[^\n]s", &temp.listingId, temp.agent,&temp.price,&temp.propertySize,&temp.numOfBeds,
           &temp.numOfBaths,&temp.yearBuilt,temp.address);
    addTreeNode(&tree, &temp);
    //}


    fclose(fp);

    return 0;
}

void init(bTree **tree){
    *tree = malloc(sizeof(bTree));
    (*tree)->node= NULL;


}

void addTreeNode(bTree **tree,bNode *temp){
    if((*tree)->node == NULL){
        (*tree)->node = temp;
        (*tree)->node->left = NULL;
        (*tree)->node->right = NULL;
    }
    else if(temp->listingId < (*tree)->node->listingId){
        addTreeNode((*tree)->node->left,temp);
    }
  /* printf("%d %s %d %d %d %.1lf %d %s\n", (*tree)->node->listingId, (*tree)->node->agent, (*tree)->node->propertySize,(*tree)->node->price, (*tree)->node->numOfBeds,
           (*tree)->node->numOfBaths, (*tree)->node->yearBuilt, (*tree)->node->address);*/
}

【问题讨论】:

    标签: c pointers recursion binary-search-tree


    【解决方案1】:

    由于您添加节点的函数具有签名

    void addTreeNode(bTree **tree,bNode *temp);
    

    你不能递归地使用它来向左子树或右子树添加节点:bTree 只保存树的根,子树是指向bNode 的指针。根据子树类型定义一个新函数,并用它来实现addTreeNode

    /* adds the new node to the tree - returns root of modified tree */
    bNode* addTreeNodeHelper(bNode *root, bNode *temp);
    
    void addTreeNode(bTree **tree,bNode *temp) {
         (*tree)->node = addTreeNodeHelper((*tree)->node, temp);
    }
    

    您现在拥有的代码改为进入帮助程序。

    void addTreeNodeHelper(bNode *root, bNode *temp){
        if (!root) {
            temp->left = temp->right = NULL;
            return temp;
        }
        else if (temp->listingId < root->listingId) {
            root->left = addTreeNodeHelper(root->left, temp);
            return root;
        ...
    }
    

    【讨论】:

    • if(!root) 实际检查什么?我知道 !意味着不是,但我还是有点困惑..
    • 这是一种常见的写法if (root==NULL)
    【解决方案2】:

    请阅读https://en.wikipedia.org/wiki/Binary_search_tree

    尤其是插入部分

    就像一直向左移动然后返回轨道然后一直向右移动

    不,二叉搜索树已经排序了。

    在伪代码中,您只需:

    node search(value,node)
    
      if node_value == search_value then return node
      else if current_node_vale <  search_value return search(left)
      else return search(right)
    

    void addTreeNode(bTree **tree,bNode *temp);

    树操作修改节点,并且该节点可能是根节点,因此您不能使用 root_node 作为树的表示。而是使用指向根节点的指针。

    typedef struct treeFrame{
        bNode *node;
    }bTree;
    

    因此,如果您的函数需要创建或修改您的树,则向它们传递指向该树的指针,它们需要使用指向树的指针,因为如果根节点发生更改,则更改需要到达调用者范围.所以所有的树函数都应该有签名:

    do_something( bTree * tree_ptr)
    

    但有些人(比如我)不喜欢这种抽象,因此他们更喜欢直接使用 root_nodes,而不是定义树结构或 typedef。

    在这种情况下,签名应该是以下类型:

    do_something( bNode ** root_node)
    

    请记住,树是指向 root_node 的指针,因此您只需添加另一个间接方法,以便能够在操作需要时更改 root_node。


    最后你的原型:

    void init(bTree **tree);
    void addTreeNode(bTree **tree, bNode *temp);
    

    错了,如果你使用 root_nodes,你需要一个双指针,或者如果你抽象树,你需要一个单指针。

    【讨论】:

    • 我尝试查找抽象,但我仍然对抽象树的含义有点困惑..
    • 一棵树 IS 是指向根节点的指针,与链表 IS 指向第一个元素的指针相同。 Abstraction 对您的代码用户隐藏了它,并说,这是一个 tree ,将它与这些功能一起使用。如何实现或使用节点不关你的事。
    猜你喜欢
    • 2017-02-19
    • 2012-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-02
    相关资源
    最近更新 更多