BST build tree double pointers

我的梦境 提交于 2019-12-19 04:13:11

问题


I am unsure how to set a pointer to a pointer to build a tree. Like once I have traveled to a leaf and call insert, how should I insert another element calling insert with the root node or the address of the root pointer? I think the problem with this function is the name root where that should be the double pointer right?

#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;
}

This is the .h file

/// 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;

and lastly the traverse function so far as it failed the first test.

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 );
    }

}

Why is the insertNode getting the errors (multiple) and I don't know which is the pointer and which is the struct. GUYS ANY HINT WILL BE HELPFUL PLEASE?

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);
  }
}

SO for Edit 2: I do have a header file which has a build_Tree(**root, elems[], sizeofElem[]), which means i need a helper function insert. Yes is would be easier to add by input starting*.

Edit 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 

Edit 2 for main and build_tree

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;
}

回答1:


Say you created a function addNodeToTree(TreeNode *root, int data), pass the root node, and data to it as argument.

Now inside this function, simply create another variable say TreeNode *current = root which will help us basically to traverse the tree and place the node at its respective position, and TreeNode *newNode = NULL(this will become the new node, which is to be inserted).

Now before moving ahead, to actually place the node, we will first check, if the root is not null, i.e. the tree is EMPTY. For that, we will test:

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;
}

If the tree is not EMPTY, i.e. it contains a node already, then we will traverse the tree to find the place, where to put the new node. So the else part, will be like:

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;
}

Now the newNode has been inserted, and you can simply traverse in any order to see the Tree.

EDIT 1:

Here is one working example, just see if this makes sense. Else please do ask any question, that might may arise.

#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;
}

EDIT 2:

To make addNodeToTree(...), implement pointer to a pointer, one simply needs to change the function as:

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
}

And the call from main will now look like:

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
}

EDIT 3:

In order to take elements from an array instead of adding them directly to tree, just change the main method to this form:

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;
}


来源:https://stackoverflow.com/questions/26395841/bst-build-tree-double-pointers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!