2

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;
}
arrowinfedex
  • 121
  • 1
  • 3
  • 11
  • Please try `if (new_node->data > (*root)->data)`, in place of `if (new_node->data > &root->data)`. `&root` specifies, address of `root`, though here since it is a pointer to a pointer, hence you need the value inside the `root`, which again is an address to some another node. – nIcE cOw Oct 16 '14 at 04:57
  • You can also use a `pointer to a pointer`, then in that case, you don't have to return anythingy from the function, since, whatever is happening inside the function is actually happening on the actual variables and not on it's copy. But if one uses just a pointer, then once has to return root, for reciprocating the changes made, back to the calling function :-) – nIcE cOw Oct 16 '14 at 05:00
  • Ok would that be for all the calls where &root is called? in the insertNode Function. – arrowinfedex Oct 16 '14 at 05:04
  • i would rather not return anything since I don't know how that would be implemented int he build tree unless I use recursion (or reciprocating the changes made, back to the calling function)) Pointers and recursion do not compile well together. – arrowinfedex Oct 16 '14 at 05:10
  • The `build_tree(...)` function, should never allocate memory for root, since this is what is being done inside, `addNodeToTree(...)` method. Is entering values to the tree, through an array mandatory? – nIcE cOw Oct 16 '14 at 14:12
  • Thanks I used a build_tree(&root, elems[], elemcount) in the parameters and found that it worked better. My professor helped me change the mallocing so I only malloc in getN, but not sure if my Tree is actually being built. Is there any fine tuning on the build_tree I can do because I don't beleive I need the parent nodes now. – arrowinfedex Oct 16 '14 at 15:13

1 Answers1

2

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;
}
nIcE cOw
  • 24,468
  • 7
  • 50
  • 143
  • So what you are saying is getNewNode is creating after traversing the tree? If that is the case than where does the parent node get created and what happens to root when addNodetoTree() is called again? I will select your answer before modifying my code once I just understand a little bit more. – arrowinfedex Oct 16 '14 at 05:05
  • @arrowinfedex: One simply gets a reference to root, as an argument to a function. Now `parent and current` simply points to the same node where `root` is pointing to. Now we move `current` to the other node, depending on, on which side of the current, the `newNode` will be placed(on account of whether the data of the newNode is > or < current Node's data). Before pusing current to point to either `left/right`, we simply making `parent = current`. In simpler terms, in this loop, we actually finding a leaf node(such that parent will point to this leaf node), – nIcE cOw Oct 16 '14 at 05:18
  • @arrowinfedex: below which our `newNode` will getplaced – nIcE cOw Oct 16 '14 at 05:19
  • Yes, perfectly makes $.02. I just don't know about changing the void insert() to return a node. How would that help build_tree(). In other words would I want to return root at the parameter of the loop: for ( i0 = 0; i0 < count; ++i0 ){ *root = addNodeToTree(TreeNode *root, int data[count]) } – arrowinfedex Oct 16 '14 at 05:25
  • @arrowinfedex: Please have a look at this. I hope, it makes sense, now as to what I wrote in comments, in the previous snippet. This working example, might can help you understand, the whole thingy in a better way. – nIcE cOw Oct 16 '14 at 06:01
  • is where I begin to compile with corrections. I have an unusual debgugging error with the scanf and printf in the main. Thank you for the help so far. nIcE cOw – arrowinfedex Oct 16 '14 at 06:13
  • How would I implement a double pointer in that code for build_tree? – arrowinfedex Oct 16 '14 at 07:49
  • @arrowinfedex: I have tried to add, a bit extra as __EDIT 2__. Though if still unclear, try not to make functions, straight forward. Just use `malloc` to allocate some space, and then add the node manually inside `main`, and get a feel of it, how thingies do move. Then slowly as you move along, try to implement that with functions. But first try simply adding nodes manually, one by one. – nIcE cOw Oct 16 '14 at 12:56
  • I can try that, but I am now using my resourcesa at the tutoring center. I prefer the no return on this edit, but there seems to be more allocating rather than pointing... – arrowinfedex Oct 16 '14 at 13:46
  • @arrowinfedex: Actually allocation is happening, only for `newNode`, when we using `malloc`, rest are just pointers shifting the addresses held by them to each other, nothing more. Since when malloc allocated a space for a node in memory, we putting that location inside `newNode`, hence when `*root == NULL`, then we have to assign that address to `root`, therefore, `*root = newNode`, since, root must point to this newly created node, to create the first node in the tree. I corrected my mistake in the snippet, just NOW :-) – nIcE cOw Oct 16 '14 at 13:50
  • Thank you. I just made an edit which says there a multiple definitions when setting **root = *root(?) and then when TreeNode *current = *root; – arrowinfedex Oct 16 '14 at 14:13
  • @arrowinfedex: Please see this latest edit, in which elements are taken from an array. – nIcE cOw Oct 16 '14 at 14:18
  • I looked at it and right now, preOrder (inOrder ) takes a *root, as far as what i have been doing, I beleive that will just be "root" not *root like I have. Thanks, for helping so far. – arrowinfedex Oct 16 '14 at 15:17
  • @arrowinfedex: Inside `main` keep everythingy as easy as possible, i.e. just pointer to somethingy. Though how thingies are implemented inside a function, is not of any concern to the outside world, their you can bring, pointer to a pointer/pointer to a pointer (to whatever level of complexity). For the rest, YOU'RE MOST WELCOME and KEEP SMILING :-) I am still thinking of some way, to make you understand, though will try to do that, if I get some idea from my classmate, how to explain that to you in easy way :-) – nIcE cOw Oct 17 '14 at 02:17