c - BST构建树双指针

标签 c debugging insert binary-search-tree code-hinting

我不确定如何设置指向指针的指针来构建树。就像一旦我到达叶子并调用 insert 一样,我应该如何插入另一个使用根节点或根指针地址调用 insert 的元素?我认为这个函数的问题是名称 root ,它应该是双指针,对吗?

#include "bst.h"
#include <stdio.h>
#include <stdlib.h>

//arbitrary list of temp nodes

TreeNode *new_node, *root, *tmp, *parent;
int elemArray[100], i1, i2, i0;


int main( int argc, char *argv[] ) {

    //Throw error is *Argv[] is not an integer
    //assuming it was an integer
    int cnt = atoi( argv[1] );
    printf( "number is %d\n", cnt );
    //
    printf("Enter %i integer values to place in tree:\n", cnt);
    for ( i1 = 0; i1 < cnt; ++i1) {
        scanf( "%d", &elemArray[i1] );
    }

    //first ouput "INput Values"

    printf( " Input Values:\n " );  
     for ( i2 = 0; i2 < cnt; ++i2) {
               printf( "%d\n", elemArray[i2] );
        }
    TreeNode** root = (TreeNode*)malloc(sizeof(TreeNode*));

    buildTree(root, elemArray, cnt );

    printf( "Preorder:\n ");

    //traverse
    //TreeNode* tempN = malloc(sizeof(TreeNode*));
    //tempN->data= 5;

    traverse( root, PREORDER);

    //traverse a single node 
    printf( "Inorder:\n ");

    printf( "Postorder:\n ");


    //Build tree with each element

    return 0;
}

这是.h文件

/// The definition of the tree structure
typedef struct TreeNode {
    int data ;                  // the data stored in the node
    struct TreeNode* left ;     // node's left child
    struct TreeNode* right ;    // node's right child
} TreeNode;

/// The three supported traversals
typedef enum {
    PREORDER,           // parent -> left -> right
    INORDER,            // left -> parent -> right
    POSTORDER           // left -> right -> parent
} TraversalType;

最后是遍历函数,因为它在第一次测试中失败了。

void traverse( const TreeNode* root, const TraversalType type ) {

    if ( type == PREORDER) {
             if (root != NULL)
             {
                printf("%d", root->data);
                traverse( root->left, PREORDER);
                traverse( root-> right, PREORDER);
            }
    }
}

void build_tree(TreeNode** root, const int elements[], const int count) {

    TreeNode* node = malloc(sizeof(TreeNode*));
    node->left = node ->right = NULL;

    *root = node;

    for ( int i0 = 0; i0 < count; ++i0 ){
        TreeNode* node = malloc(sizeof(TreeNode*));
        *root = node;
        node->data = elements[cnt];
        insertNode( &(*root), &node );
    }

}

为什么 insertNode 会出现错误(多个),而且我不知道哪个是指针,哪个是结构。各位,有什么提示会有帮助吗?

bst.c:94:20: error: request for member 'left' in something not a structure or union
         insert(root->left, new_node);


void insertNode(TreeNode** root, TreeNode* new_node) {

   if (new_node-> data < &root-> data) {
      if (&root-> left == NULL) 
         &root-> left == new_node;
      else
        insert(root->left, new_node);
   }

  if (new_node->data > &root->data) {
    if(&root-> right ==NULL)
      &root->right = new_node;
    else
      insert(&root->right, new_node);
  }
}

编辑2的SO:我确实有一个头文件,其中有一个build_Tree(**root, elems[], sizeofElem[]),这意味着我需要插入一个辅助函数。是的,通过输入开始*来添加会更容易。

编辑 1

#include "bst.h"
#include <stdio.h>
#include <stdlib.h>

//arbitrary list of temp nodes

TreeNode *new_node, *root, *tmp, *parent, *current;
int elemArray[5], i1, i2, i0;

/*
Insert a new node into the tree by referencing the root and using recursion
*/

    TreeNode* getN(int dataElem) {
        TreeNode *newNode = malloc(sizeof(*newNode));
        if (newNode != NULL)
        {
            newNode->data = dataElem;
            newNode->left = NULL;
            newNode->right = NULL;
        }

        return newNode;
    } 

/** This func should just be the root of the tree in the parameter, 
but I like the idea of a pointer becuase it helps to create a tempory 
pointer rather than newNode
**/


TreeNode* addNodeToTree(TreeNode *root, int data) {

    TreeNode *current = *root; //define the current pointer to the root always
    TreeNode *parent = *root
    TreeNode *newNode = getN(data);

    if (*root == NULL)
    {
        printf("First Node");
        *root = newNode;
    }
    else
    {
        while(current != NULL)
        {
            parent = current;
            if (current->data > data)
                current = current->left;
            else if (current->data < data)
                current = current->right;
        }

        if (parent->data > data)
            parent->left = newNode;
        else if (parent->data < data)
            parent->right = newNode;
    }
}



void build_Tree(TreeNode** root, const int elements[], const int count) {

    *root = malloc(sizeof(TreeNode));

    for ( i0 = 0; i0 < count; ++i0 ){
        printf("%d\n", elements[count]);
        addNodeToTree(&root, elements[count]);
    }

}


int main( int argc, char *argv[] ) {

    //Throw error is *Argv[] is not an integer
    //assuming it was an integer
    int cnt = atoi( argv[1] );
    printf( "number is %d\n", cnt );
    //
    printf("Enter %i integer values to place in tree:\n", cnt);
    for ( i1 = 0; i1 < cnt; ++i1) {
        scanf( "%d", &elemArray[i1] );
    }


    //first ouput "INput Values"

    printf( " Input Values:\n " );  

     for ( i2 = 0; i2 < cnt; ++i2) {
               printf( "%d\n", elemArray[i2] );
               printf("building tree0\n");
        }

    printf("building tree\n");
    TreeNode** root = (TreeNode**)malloc(sizeof(TreeNode*));
    TreeNode *root = NULL;
    build_Tree(root, elemArray, cnt );
    printf( "Preorder:\n ");

    //traverse
    //TreeNode* tempN = malloc(sizeof(TreeNode*));
    //tempN->data= 5;

    traverse( *root, PREORDER);             //pass the pointer of root to traverse the tree

    //traverse a single node 
    printf( "Inorder:\n ");

    printf( "Postorder:\n ");


    //Build tree with each element

    return 0;
}

void traverse( const TreeNode* root, const TraversalType type ) {

    if ( type == PREORDER) {
             if (root != NULL)
             {
                printf("%d", root->data);
                traverse( root->left, PREORDER);
                traverse( root-> right, PREORDER);
            }
    }
}




    /**
    void insertNode(TreeNode** root, TreeNode* new_node) {

       if (new_node-> data < *root-> data) {
          if (*root-> left == NULL) 
             *root-> left == new_node;
          else
            insert(*root->left, new_node);
       }

      if (new_node->data > *root->data) {
        if(*root-> right ==NULL)
          *root->right = new_node;
        else
          insert(*root->right, new_node);
      }
    }
    **/


//question1: what is the 

编辑 main 和 build_tree 2

void build_Tree(TreeNode** root, const int elements[], const int count) {

    //*root = malloc(sizeof(TreeNode));

    for ( i0 = 0; i0 < count; i0++ ){

        //create the node
        //
        TreeNode *current = *root; //define the current pointer to the root always
        TreeNode *parent = *root;
        //dont create node
        int data = elements[i0];
        TreeNode *newNode = getN(data);

        if (*root == NULL)
        {
            printf("First Node %d\n", elements[i0]); 
            *root = newNode;
        }
        else
        {
            printf("Next Node %d\n", elements[i0]); 
            while(current != NULL)
            {
                parent = current;
                if (current->data > data)
                    current = current->left;
                else if (current->data < data)
                    current = current->right;
            }

            if (parent->data > data)
                parent->left = newNode;
            else if (parent->data < data)
                parent->right = newNode;
        }
        //return root;
    }
}

    TreeNode* getN(int dataElem) {
        TreeNode *newNode = malloc(sizeof(*newNode));
        if (newNode != NULL)
        {
            newNode->data = dataElem;
            newNode->left = NULL;
            newNode->right = NULL;
        }

        return newNode;
    } 

int main( int argc, char *argv[] ) {

    //Throw error is *Argv[] is not an integer
    //assuming it was an integer
    int cnt = atoi( argv[1] );
    printf( "number is %d\n", cnt );
    //
    printf("Enter %i integer values to place in tree:\n", cnt);
    for ( i1 = 0; i1 < cnt; ++i1) {
        scanf( "%d", &elemArray[i1] );
    }


    //first ouput "INput Values"

    printf( " Input Values:\n " );  

     for ( i2 = 0; i2 < cnt; ++i2) {
               printf( "%d\n", elemArray[i2] );
               printf("building tree0\n");
        }

    printf("building tree\n");
    TreeNode* root; //= malloc(sizeof(TreeNode*));
    root = NULL;
    build_Tree(&root, elemArray, cnt );
    printf( "Preorder:\n ");

    //traverse
    //TreeNode* tempN = malloc(sizeof(TreeNode*));
    //tempN->data= 5;

    //traverse( *root, PREORDER);               //pass the pointer of root to traverse the tree

    //traverse a single node 
    printf( "Inorder:\n ");

    printf( "Postorder:\n ");


    //Build tree with each element

    return 0;
}

最佳答案

假设您创建了一个函数 addNodeToTree(TreeNode *root, int data),将 root 节点和 data 作为参数传递给它.

现在,在这个函数中,只需创建另一个变量,例如 TreeNode *current = root ,这将帮助我们基本上遍历树并将节点放置在其各自的位置,以及 TreeNode *newNode = NULL(这将成为要插入的新节点)。

现在,在继续实际放置节点之前,我们将首先检查root是否不为空,即树是否为EMPTY。为此,我们将测试:

if (root == NULL)
{
    newNode = malloc(sizeof(*newNode)); // else we can make a function for this 
                                        // thingy too. Creating a function too,
                                        // for you to look at.
    root = newNode;
}

如果树不是EMPTY,即它已经包含一个节点,那么我们将遍历树以找到放置新节点的位置。所以 else 部分将类似于:

else
{
    parent = current = root;
    // This loop will actually help us, find the `parent`, 
    // of the `newNode`(which is to be inserted)
    while (current != NULL)
    {
        parent = current;
        if (current->data > data)
            current = current->left;
        else if (current->data < data)
            current = current->right;
    }
    // Now once, we have found, the node, under which the
    // newNode will be placed, now we have to check, whether
    // newNode will become a `left child/right child` of the 
    // parent.
    newNode = getNewNode(data);
    if (parent->data > data)
        parent->left = newNode;
    else if (parent->data < data)
        parent->right = newNode;


    return root;
}

TreeNode * getNewNode(int data)
{
    TreeNode *newNode = malloc(sizeof(*newNode));
    if (newNode != NULL)
    {
        newNode->data = data;
        newNode->left = NULL;
        newNode->right = NULL;
    }

    return newNode;
}

现在 newNode 已被插入,您可以简单地以任意顺序遍历来查看树。

编辑1:

这是一个工作示例,看看这是否有意义。否则,请提出可能出现的任何问题。

#include <stdio.h>
#include <stdlib.h>

typedef struct TREENODE
{
    int data;
    struct TREENODE *left;
    struct TREENODE *right;
}TreeNode;

void display(TreeNode *node)
{
    printf("*********************************\n");
    printf("Address of Node: %p\n", node);
    printf("Data: %d\n", node->data);
    printf("Left Child: %p\n", node->left);
    printf("Right Child: %p\n", node->right);
    printf("*********************************\n");
}

TreeNode * getNewNode(int data)
{
    TreeNode *newNode = malloc(sizeof(*newNode));
    if (newNode != NULL)
    {
        newNode->data = data;
        newNode->left = NULL;
        newNode->right = NULL;
    }

    return newNode;
}

int getIntData(char *message)
{
    int value = 0;
    char buffer[BUFSIZ] = {'\0'};
    fputs(message, stdout);
    fgets(buffer, sizeof(buffer), stdin);
    sscanf(buffer, "%d", &value);

    return value;
}

TreeNode * addNodeToTree(TreeNode *root, int data)
{
    TreeNode *current = root, *parent = root;
    TreeNode *newNode = getNewNode(data);

    if (root == NULL)
    {
        root = newNode;
    }
    else
    {
        while(current != NULL)
        {
            parent = current;
            if (current->data > data)
                current = current->left;
            else if (current->data < data)
                current = current->right;
        }

        if (parent->data > data)
            parent->left = newNode;
        else if (parent->data < data)
            parent->right = newNode;
    }

    return root;
}

void inOrderTraversal(TreeNode *root)
{
    if (root != NULL)
    {
        inOrderTraversal(root->left);
        display(root);
        inOrderTraversal(root->right);
    }
}

int main(void)
{
    TreeNode *root = NULL;
    int data = 0;
    data = getIntData("Enter Data: ");
    root = addNodeToTree(root, data);
    data = getIntData("Enter Data: ");
    root = addNodeToTree(root, data);
    data = getIntData("Enter Data: ");
    root = addNodeToTree(root, data);
    inOrderTraversal(root);

    return EXIT_SUCCESS;
}

编辑2:

要使 addNodeToTree(...) 实现指向指针的指针,只需将函数更改为:

void addNodeToTree(TreeNode **root, int data)
{
    TreeNode *current = *root;
    TreeNode *parent = *root;
    TreeNode *newNode = getNewNode(data);

    if (*root == NULL)
    {
        *root = newNode;
    }
    else
    {
        // same as before, just don't return anythingy, from the function.
        // As the function uses pointer to a pointer, hence whatever changes
        // are done, here will be reciprocated in the main function automatically
    }

    // no need to return anythingy
}

来自 main 的调用现在如下所示:

int main(void)
{
    TreeNode *root = NULL;
    int data = 0;
    data = getIntData("Enter Data: ");
    addNodeToTree(&root, data);
    // Just see the call to addNodeToTree(...), the rest is same, as before
}

编辑3:

为了从数组中获取元素而不是将它们直接添加到树中,只需将 main 方法更改为以下形式:

int main(void)
{
    TreeNode *root = NULL;
    int element[5] = {19, 11, 5, 28, 25};
    int size = sizeof(element) / sizeof(element[0]);
    int counter = 0;
    for (counter = 0; counter < size; ++counter)
    {
        addNodeToTree(&root, element[counter]);
    }
    inOrderTraversal(root);

    return EXIT_SUCCESS;
}

关于c - BST构建树双指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26395841/

相关文章:

objective-c - 如何根据对象字符串属性在 Xcode 中设置条件断点?

debugging - 查找 <<loop>> 发生的位置

php - MYSQL insert or update if exists on one-way composite primary key table 单向复合主键表

sql-server - 使用 SqlClient 类时如何在 SQL Server 中获取插入的 ID?

c# - 当程序崩溃而没有异常时如何调试程序?

c++ - 如何从 C 执行命令并终止它

c - Opencv CV ColorHSV错误

c - 将指针传递给字符串指针数组

C 在链表开头插入元素

c - 使用 Green Hills 编译器将静态库与 header 链接起来