C中的二叉树遍历没有输出

时间:2017-05-13 08:25:37

标签: c function pointers data-structures binary-tree

我是菜鸟程序员,我有一个暗示使用二叉树的项目。我所要做的就是插入一个节点,删除一个节点并添加两个树遍历方法。问题是我无法使用我的代码。我决定添加一些辅助函数,如check_element和create_NewNode,以帮助我更轻松地实现。我在运行后没有在控制台上获得输出,或者只是因为运行时错误问候我。我有一个头文件,IO.c文件来存储我的函数和main.c.to测试头文件已实现的函数。

Here is IO.c , used to store the functions.



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

    struct node{
        int data;
        struct node *left;
        struct node *right;

    };

    struct node *root;


    /*-----------------------------------------------------------------------------------------*/

        //function to determine if an element is already in the tree
    void check_element( struct node *node, int value)
    {
        while( node != NULL ){
            //checking if the value is here
            if( value == node->data ){
                printf("The element %d already exists in the tree!",value);
                exit(0);
            //if the value is smaller, go left
            }else if( value < node->data ){
                check_element( node->left, value );
            //else go right
            }else if( value > node->data ){
                check_element( node->right, value );
            //else the element was not found and we can add it to th tree
            }else{
                printf("Adding the element %d to the tree.",value);
                exit(0);
            }

        }//end while

    }//end check_element



    /*-----------------------------------------------------------------------------------------*/


        //helper function to crate a new node and set left and right pointers to NULL
    struct node *create_NewNode(  int value )
    {
        struct node *ptr;
        struct node *temp = (struct node*)malloc(sizeof(struct node));
        ptr = (struct node*)malloc(sizeof(struct node));

        if( ptr == NULL){
            printf("Memory allocation error!");
            exit(-1);
        }

        //assigning the data to the newly created node
        temp->data = value;

        //setting left and right pointers to NULL
        temp->left = NULL;
        temp->right = NULL;

        return temp;
    }


    /*-----------------------------------------------------------------------------------------*/


        //function to add a new value to the tree;
    struct node *insert_value( struct node *node, int new_value )
    {

        //checking if the element already exists to the tree
        check_element( node, new_value );

        //checking if the tree is empty
        if( node == NULL ){
            node = create_NewNode( new_value );
        //if the value is smaller, we add it to the left
        }else if( new_value < node->data ){
            insert_value( node->left, new_value );
        //else we add it to the right
        }else{
             insert_value( node->right, new_value );
        }

        return node;

    }


    /*-----------------------------------------------------------------------------------------*/


    void printPostorder( struct node *node )
    {
         if (node == NULL){
                printf("The tree is empty!");
                exit(0);
         }else{
                //first go left
                printPostorder( node->left );

                //then go right
                printPostorder( node->right );

                //finally, print the node value
                printf("%d", node->data);

         }
    }


    /*-----------------------------------------------------------------------------------------*/


    void inorder_traversal( struct node *node )
    {
       if( node == NULL) {
            printf("The tree is empty!");
            exit(0);
       }else{
            //first go left
            inorder_traversal( node->left );

            //print the node value
            printf("%d ",node->data);

            //then go right
            inorder_traversal( node->right );

       }
    }


    /*-----------------------------------------------------------------------------------------*/




This is the header file, called Library.h



 //prototype for NewNode
struct node *create_NewNode( int value );
    //prototype for insert_value
struct node *insert_value( struct node *node, int new_value );
    //prototype for printPostordre
void printPostorder( struct node* node);
    //prototype for printInorder
void inorder_traversal( struct node *node );
    //prototype for check_element
void check_element( struct node *node, int value);



And, finally, the main.c: `enter code here:



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

    int main()
    {
        // TEST CODE

        struct node *root;
        root = NULL;

        insert_value(root, 1);
        insert_value(root, 2);
        insert_value(root, 3);


         printPostorder( root );
        inorder_traversal( root );







        return 0;
    }


PS: I did my best to write this code, but, as I said, I am a rookie and I'm pretty bad at coding.I'd also like to appologize for any grammar mistakes, i am not an englishman.

2 个答案:

答案 0 :(得分:1)

可能会有更多错误,但我读了create_node()并希望就此提出建议:

struct node *create_NewNode(  int value )
{
    struct node *ptr;
    struct node *temp = malloc(sizeof(struct node));
    ptr = malloc(sizeof(struct node));

    if( ptr == NULL){
        printf("Memory allocation error!");
        exit(-1);
    }

    //assigning the data to the newly created node
    temp->data = value;

    //setting left and right pointers to NULL
    temp->left = NULL;
    temp->right = NULL;

    return temp;
}

在这里,您要创建两个节点,而您只想创建一个节点。您将temp视为新的,而忘记了ptr。您不需要创建另一个节点!

您需要的是树的指针,以便在该树中添加新构造的节点(因此您可以将另一个参数传递给该函数,即树的指针)。

顺便说一下,我删除了malloc的强制转换,如Do I cast the result of malloc?

中所述

我建议在我的建议之后尝试修复您的代码。但是,我会将您链接到treemanagement.c,这是树的代码,完全注释,这是我了解此数据结构的方式,它可能会派上用场未来!

答案 1 :(得分:0)

我忘记了这篇文章。我有它工作。这是我用过的:

对于标头文件:

///\file Header.h
///\brief The header containing all the prototypes for our functions.
struct node *Create_node( int value );
void delete_value(struct node **root, int val_del) ;
void inorder_traversal( struct node *node );
void insert_value( struct node **head,  int new_value );
void pre_order_traversal( struct node* node );
struct node* search_by_value(struct node* node, int value);
int random_value_generator(int domain);

用于实现功能:

    ///\file Functions.c
///\brief C library implementation for BST.
#include <stdio.h>
#include <stdlib.h>
#include "Header.h"

//In this structure we'll be storing our BST.
struct node{
    ///\struct struct node
    ///\brief It represents our structure to store our BST.

    int data;
    struct node *left;
    struct node *right;

};





/*-----------------------------------------------------------------------------------------------------*/

    /*
        Helper function which creates a new node, containing the desired value and setting left and right
        pointers to NULL.
    */
struct node *Create_node( int value )
{
    ///\fn struct node *Create_node(int value)
    ///\brief Returns a new node, initialised with "value" and 2 NULL pointers, left and right.
    ///\param value The value which we want to initiliase the newly created node with.
        //Creating the new Node and allocating memory to it.
    struct node *new_node = (struct node*)malloc(sizeof(struct node));
        //Assigning the desired value to the newly created node.
    new_node->data = value;
        //Setting left and right pointers to NULL;
    new_node->left = NULL;
    new_node->right = NULL;

    return new_node;
};


/*-----------------------------------------------------------------------------------------------------*/



    /*
        The first traversal method.
    */


void pre_order_traversal( struct node* node )
{
    ///\fn pre_order_traversal(struct node* node)
    ///\brief A function used to 'traverse' the tree. It actually is a printing function.
    ///\param node It represents the starting point of printing.
        //Checking if the tree is not empty.
   if( node != NULL ) {
    ///It will print the root, then the left child, then the right child.
        //Printing the node.
      printf( "%d ",node->data );
        //Printing the left child.
      pre_order_traversal( node->left );
        //Printing the right child.
      pre_order_traversal( node->right );
   }
}


/*-----------------------------------------------------------------------------------------------------*/


    /*
        A function which inserts a new node in the tree.
    */
void insert_value( struct node **head,  int new_value )
{
    ///\fn  insert_value(struct node **head,  int new_value)
    ///\brief Inserts a new node into our BST.
    ///\param head This parameter is passed as a double pointer to avoid any conflicts with other fucntions.
    /// and represents the starting point of insertion. The function will start searching for the appropriate
    /// position to insert the value.
    ///\param new_value Is the new value which will be assigned to the new node;

        //Initialising the pointer.
    struct node *current = *head;
        //Checking if the the current node is NULL, if it is, we create a new node.
    if( current == NULL){
        //If the root is NULL, then we create a new new node, containing the new value.
        current = Create_node( new_value );
        *head = current;
    }else{
        //Else, if the value is smaller, recur to the left.
        if( new_value < current->data ){
            insert_value( &current->left, new_value );
        }else{
            //Else recur to the right.
            insert_value( &current->right, new_value );
        }

    }
}



/*-----------------------------------------------------------------------------------------------------*/

    /*
        The second traversal method.
    */

void inorder_traversal( struct node *node )
{
    ///\fn inorder_traversal(struct node* node)
    ///\brief A function used to 'traverse' the tree. It actually is the second printing function.
    ///\param node It represents the starting point of printing.
   if( node != NULL ) {
        ///It will print the left child, then the root, then the right child.
        //Printing the left child.
      inorder_traversal( node->left );
        //Printing the root.
      printf( "%d ",node->data );
        //Printing the right child.
      inorder_traversal( node->right );
   }
}




/*-----------------------------------------------------------------------------------------------------*/


    /*
        A function which deletes a node.
    */
void delete_value(struct node **root, int val_del)
{
    ///\fn void delete_value(struct node **root, int val_del)
    ///\brief It is the most complex function and it is used to delete a node.
    /// There are multiple cases of deletion, such as: a leaf node (a node without any children),
    /// a node with a child on the right, a node with a child on the left or a node with 2 children.

    //We are starting from root, with two pointers: current and parent.
    struct node *current = *root;
    struct node *parent;

    //We recur on the tree untill we find the node containing the value which we want to remove.
    while (current->data != val_del) {
        //Moving the parent to root. The root's parent is NULL. (root has no parent)
        parent = current;
            //If the value is greater the parent's value, recur right.
        if (current->data > val_del) {
            current = current->left;
        }else{
            //Else recur left.
            current = current->right;
        }
    }

    //Checking if the node is a leaf node. (no children on the left or right)
    if ((current->left == NULL) && (current->right == NULL)) {
            //Comparing the node's value with the value of its parent.
            //If the value is smaller, we remove the left children.
        if (current->data < parent->data) {
            parent->left = NULL;
        }else{
            //Else we remove the right child.
            parent->right = NULL;
        }
        free(current);
    //Else, we check if it has a child on the left.
    }else if (current->right == NULL) {
                //Checking if our node is the root.
            if(current == *root) {
                //Using an aux to free the root, so the memory is not allocated to it anymore .
                struct node *aux;
                aux = (*root)->left;
                free(*root);
                (*root) = aux;
                //If the node is not the root, we proceed.
            }else{
                    //If the node's parent value is greater the the value of our node. If true, we replace
                    //the parent's left child with its left succesor and remove (free) the node.
                if (current->data < parent->data) {
                    parent->left = current->left;
                    free(current);
                }else{
                    //Else, we do the same thing, but for the parent's right child.
                    parent->right = current->left;
                    free(current);
                }
            }
     //Else, we check if it has a child on the right.
    }else if(current->left == NULL) {
                //Checking if our node is the root.
            if(current == *root) {
                //Using an aux to free the root, so the memory is not allocated to it anymore.
                struct node *aux;
                aux = (*root)->right;
                free(*root);
                *root = aux;
                //If the node is not the root, we proceed.
            }else {
                if (current->data < parent->data){
                        //If the node's parent value is smaller the the value of our node. If true, we replace
                        //the parent's left child with its right succesor and remove (free) the node.
                        //It is the mirrored code of the previous case.
                        parent->left = current->right;
                        free(current);
                }else{
                        //Else, we do the same thing, but for the parent's right child.
                        parent->right = current->right;
                        free(current);
                }
            }
    //Else, the node has 2 children. This is the last case.
    }else if( (current->right != NULL) && (current->left != NULL)){
            //In order to replace the root, we need to go one step to the right,
            //and then all the way to the left, retrieve the smallest value,
            //which will replace the root.
            struct node *temp = current->right;
            int aux;
            while (temp->left != NULL) {
                    temp = temp->left;
            }
            //This si where we do the swap.
            aux = temp->data;
            current->data = aux;
            temp = temp->right;
    }
}


/*-----------------------------------------------------------------------------------------------------*/


    /*
        Helper function to determine if a value already exists in the tree.
    */
struct node* search_by_value(struct node* node, int value)
{
    ///\fn struct node* search_by_value(struct node* node, int value)
    ///\brief It is a function used to check if an element already exists in the tree.
    /// If the fucntion returns NULL, it means that the element DOESN'T belong to the tree.

        //Checking if the current node is empty or it has the value which we are looking for.
    if (node == NULL || node->data == value){
             return node;
             free(node);
    }

        //If the value is greater, recur right.
    if( value > node->data ){
            return search_by_value(node->right, value);
    }else{
                //Else recur left.
            return search_by_value(node->left, value);
    }
    //Returning NULL if the element wasn't found.
    return NULL;
}


/*-----------------------------------------------------------------------------------------------------*/

    /*
    A simple function to generate random numbers,
    between 0 and a domain.
    */
int random_value_generator(int domain)
{
    ///\fn int random_value_generator(int domain)
    ///\brief It generates random numbers between 0 and a set domain.
    ///\param domain It represents the dmain.(the upper boundry for our generation)
    return rand()%domain;
}

最后是主文件:

///\file main.c
///\brief The driver program for our BST library, containing a command line.
#include <stdio.h>
#include <stdlib.h>
#include "Header.h"

//Setting the root to NULL.(empty tree)
struct node *root=NULL;

int main()
{
    //Preparing the command line. The choice is like a task selector.
    int choice;

    //Infinitely recuring until the user decides to exit or there is an error.
    do{
        //Printing the command line and acquiring the choice.
        printf("\nWhat would you like to do ? Select:");
        printf("\n1-Add value;\n2-Delete value;\n3-Print In-Order;\n4-Print Pre-Order;\n5-Random;\n6-Exit;");
        printf("\n");
        printf("\nYour choice:");
        scanf("%d",&choice);

        switch(choice){

            //The first case is used for insertion of a new value.
            case 1:{
                //Initialising the local values.
                int iterations=0,number=0,value=0,iterator=0;
                //Setting up a pointer, for later use.
                struct node *ptr;
                //Acquiring the number of iterations.
                printf("\nHow many values would you like to insert? Type a value:");
                scanf("%d",&iterations);

                //Inserting values as many times as we initiliased "iterations".
                while( number < iterations ){
                    printf("\nValue[%d]=",iterator);
                    scanf("%d",&value);

                    //Using the pointer to check if the value already exists.
                    ptr = search_by_value( root, value );

                    if( ptr == NULL ){
                            //In case of ptr = NULL, we add it to the BST.
                            insert_value(&root,value);
                            value = 0;
                    }else{
                        //Else we ask for another value, without affectig the number of iterations.
                        printf("\nThe element %d already exists in the tree!",value);
                        //Resetting the pointer and the vaue to be reused.
                        value = 0;
                        ptr = NULL;
                        //A simple way to keep the loop consistent.
                        //If we want to insert 10 values and 1 would already exists,
                        //we would only have 9 values. This way, even if there a values
                        //already exists, we will still have to insert the appropriate
                        //nuber of values.
                        number--;
                        iterator--;
                    }
                    //Incrementing the iterators to prevent an ifinite loop.
                    number++;
                    iterator++;
                }
                //Reseting the iterator to be used later.
                iterator=0;
                break;
            };//end case-1

            //The second case is used for deletion.
            case 2:{
                //Initialising the value.
                int d_value=0;
                //Acquiering the value we want to delete.
                printf("\nWhich value would you like to delete? \nType a value:");
                scanf("%d",&d_value);

                //Checking if the value exists in the tree.
                struct node *ptr = search_by_value( root, d_value );

                if( ptr != NULL ){
                    //If ptr != NULL, it means that the value exists in the tree
                    // and it can be deleted.
                    printf("\nDeleting %d !",d_value);
                    //Deleting the value.
                    delete_value(&root, d_value);
                    //Reseting the value for laer use
                    d_value = 0;
                }else if( ptr == NULL ){
                    //Else the value does not belong to the tree, so it cannot be deleted.
                    printf("\nThe element %d doesn't belong to the tree!",d_value);
                    printf("\n");
                    //Resetting the pointer and the value for later use.
                    d_value = 0;
                    ptr = NULL;

                }else{
                    //Else our tree is empty.
                    printf("\nEmpty Tree!");
                }
                break;
            };//end case-2

            //The third case is used for in-order traversal.
            case 3:{
                printf("\nIn-order traversal:");
                inorder_traversal(root);
                printf("\n");
                break;
            };//end case-3

            //The fourth case is used for pre-order traversal.
            case 4:{
                printf("\nPre-order traversal:");
                pre_order_traversal(root);
                printf("\n");
                break;
            };//end case-4

            //The fifth case is used for randomly inserting value into teh BST.
            case 5:{
                //Initialising the values.
                int iterations=0,number=0,value=0,iterator=0,domain=0;
                //Setting up a pointer for later use.
                struct node *ptr;
                //Acquiering the number of iterations.
                printf("\nHow many values would you like to insert? Type a value:");
                scanf("%d",&iterations);

                //Acquiering the domain for the random generator.
                printf("\nPlease type the domain for the randomly generated numbers.");
                printf("\nPlease type a value:");
                scanf("%d",&domain);

                //Iterating until all the values have been successfully inserted.
                while( number < iterations ){
                    //The new value to be inserted is generated using our fucntion.
                    value = random_value_generator(domain);

                    //Checking if the values already exists in the tree.
                    ptr = search_by_value( root, value );

                    if( ptr == NULL ){
                            printf("\nInserting %d!",value);
                            //If ptr = NULL, we can safely insert the value into our BST.
                            insert_value(&root,value);
                            //Resetting the value for later use.
                            value = 0;
                    }else{
                        //Else, we cannot insert the value, as it already exists.
                        printf("\nThe element %d already exists in the tree!",value);
                        //Resetting the pointer and the value.
                        value = 0;
                        ptr = NULL;
                        //Same trick to insert the exact number of values.
                        number--;
                        iterator--;
                    }
                    //Incrementing to prevent infinite looping.
                    number++;
                    iterator++;
                }
                //Resetting the iterator for later use.
                iterator=0;
                break;

            };//end case-5

            //The sixth case is used to exit the proram at will.
            case 6:{
                exit(0);
            };//end case-6

            //The default case occurs in case of error. (hope not)
            default :{
                 printf("\nError!");
                 exit(-1);
            };//end default

        }//end switch

    }while(1);//end while

    return 0;
}

我使用了双指针,摆脱了我的问题。我希望这会对某人有所帮助。