简体   繁体   English

在C99中创建二进制搜索树

[英]Creating a binary search tree in C99

I've got a programming class assignment due tonight at 8 PM CDT that I'm having trouble with. 我要在今晚晚上8点CDT进行编程课程作业,这很麻烦。 We are to take a list of the following numbers via reading a file: 我们将通过阅读文件获取以下数字的列表:

9 30 20 40 35 22 48 36 37 38 9 30 20 40 35 22 48 36 37 38

place them in an array (easy enough), and then read these into a binary search tree using C. The first number in the list is the number of elements in the tree. 将它们放置在一个数组中(足够容易),然后使用C将它们读入二叉搜索树中。列表中的第一个数字是树中元素的数量。 The rest are placed into the following struct: 其余的放入以下结构:

typedef struct node_struct {
    int data;
    struct node_struct* left;
    struct node_struct* right;
} Node;

I think I've got the first part down pat. 我想我已经拍了第一部分。 Take the stuff in using fscanf (I didn't choose to use this method, I like fgets better), call an insertion function on each member of the array, then call a "createNode" function inside the insertion function. 使用fscanf进行学习(我没有选择使用此方法,我更喜欢fgets),在数组的每个成员上调用插入函数,然后在插入函数内部调用“ createNode”函数。

Problem is, I'm only getting one member into the BST. 问题是,我只让一名成员加入BST。 Furthermore, the BST must satisfy the condition node->left->data <= node->data < node->right->data ... in other words, the nodes must be in order in the tree. 此外,BST必须满足条件node->left->data <= node->data < node->right->data ...换句话说,节点必须在树中顺序排列。

Here's what I have so far: 这是我到目前为止的内容:

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

// def BST node struct
typedef struct node_struct {
    int data;
    struct node_struct* left;
    struct node_struct* right;
} Node;

// prototypes
Node* createNode(int data);
Node* bstInsert(Node* root, int data);
// helper function prototypes
void padding(char ch, int n);
void displayTree(Node* root, int depth);

int main(int argc, char **argv)
{
    FILE *in = NULL;
    int num_read, count=0, array_size = 0;

    if(argc != 2){
        printf("hw3 <input-file>\n");
        return 1;
    }

    in = fopen(argv[1], "r");

    if(in == NULL){
        printf("File can not be opened.\n");
        return 2;
    }

    // read in the first line to get the array size
    fscanf(in, "%d", &array_size);

    // declare the array
    int array[array_size];  

    // read from the second line to get each element of the array
    while(!feof(in)){
        fscanf(in, "%d", &num_read);
        array[count] = num_read;
        count++;
    }
    fclose(in);

    if (array_size != count) {
        printf("data error. Make sure the first line specifies the correct number of elements.");
        return 3;
    }

    Node *root1 = NULL, *root2 = NULL, *root3 = NULL;

    int i;
    // task1: construct a bst from the unsorted array
    printf("=== task1: construct a bst from the unsorted array ===\n");
    for (i = 0; i < array_size; i++) {
        root1 = bstInsert(root1, array[i]);
    }
    displayTree(root1, 0);
    return 0;
}   

Node* bstInsert(Node* root, int data) {
    if(root == NULL){
        root = createNode(data);

        if(root != NULL){
            root= createNode(data);
        }

        else{
            printf("%d not inserted, no memory available.\n", data);
        }
    }

    Node* current, previous, right;
    current = root;
    previous = root->left;
    next = root->right;
    else{
        if(previous->data <= current->data){

                }


     }
     return root;
}

Node* createNode(int data) {
    // TODO
    Node* aRoot;
    if(!data)
        return NULL;

    aRoot = malloc(sizeof(Node));
    if(!aRoot){
        printf("Unable to allocate memory for node.\n");
        return NULL;
    }
    aRoot->data = data;
    aRoot->left = NULL;
    aRoot->right = NULL;
    return aRoot;
}

    /* helper functions to print a bst; You just need to call displayTree when visualizing a bst */
void padding(char ch, int n)
{
    int i;
    for (i = 0; i < n; i++)
    printf("%c%c%c%c", ch, ch ,ch, ch);
}

void displayTree(Node* root, int depth){
    if (root == NULL) {
        padding (' ', depth);
        printf("-\n");
    }
    else {
        displayTree(root->right, depth+1);
        padding(' ', depth);
        printf ( "%d\n", root->data);
        displayTree(root->left, depth+1);
    }
}

main , createNode , displayTree , and padding are okay, I believe. 我相信maincreateNodedisplayTreepadding都可以。 It's bstInsert where I'm having trouble. 我遇到麻烦的是bstInsert I'm just not sure how to order things to create a valid tree. 我只是不确定如何命令事物来创建有效的树。

EDIT: 编辑:

I've edited bstInsert and injected some more logic. 我已经编辑了bstInsert并注入了更多逻辑。 It should be printing out more leaves on the tree, but alas, it's only printing out the number "30". 应该在树上打印出更多的叶子,但是,可惜,它只打印出数字“ 30”。 Here's the new function. 这是新功能。

Node* bstInsert(Node* root, int data) {


if(root == NULL){
    root = createNode(data);

    if(root != NULL){
        root= createNode(data);
    }

    else{
        printf("%d not inserted, no memory available.\n", data);
    }
}
else{
    if(data < root->data){
        bstInsert(root->left, data);
    }
    else if(data > root->data || data == root->data){
        bstInsert(root->right, data);
    }
        }
return root;
}

You have to assign the newly created node pointer to the correct part of the tree. 您必须将新创建的节点指针分配给树的正确部分。 This code does that. 这段代码做到了。 The key change is using the return value from bstInsert() correctly. 关键的更改是正确使用bstInsert()的返回值。 The other changes are cosmetic. 其他变化是外观。 Note that I checked the input array by printing it out; 注意,我通过打印输出来检查输入数组。 also, it is sensible to print out the BST as you build it. 同样,在构建BST时将其打印出来是明智的。

Don't use feof() as a loop control condition. 不要将feof()用作循环控制条件。 It is almost invariably wrong when used as a loop control, but at least you have to also check the input operation that follows. 当用作循环控件时,这几乎总是错误的,但是至少您还必须检查随后的输入操作。 I've written a lot of programs in my time; 我当时写了很多程序; I've hardly ever used feof() (I found two places in my own code with it; in both, it was correctly used to distinguish between EOF and an error after an input had failed.) 我几乎从未使用过feof() (我在自己的代码中发现了两个地方;在这两个地方,它都正确地用于区分EOF和输入失败后的错误。)

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

// def BST node struct
typedef struct node_struct
{
    int data;
    struct node_struct* left;
    struct node_struct* right;
} Node;

// prototypes
Node *createNode(int data);
Node *bstInsert(Node *root, int data);
// helper function prototypes
void padding(char ch, int n);
void displayTree(Node *root, int depth);

int main(int argc, char **argv)
{
    FILE *in = NULL;
    int num_read, count=0, array_size = 0;

    if (argc != 2)
    {
        printf("hw3 <input-file>\n");
        return 1;
    }

    in = fopen(argv[1], "r");

    if (in == NULL)
    {
        printf("File can not be opened.\n");
        return 2;
    }

    // read in the first line to get the array size
    fscanf(in, "%d", &array_size);

    // declare the array
    int array[array_size];  

    // read from the second line to get each element of the array
    while (count < array_size && fscanf(in, "%d", &num_read) == 1)
        array[count++] = num_read;
    fclose(in);

    if (array_size != count)
    {
        printf("data error. Make sure the first line specifies the correct number of elements.");
        return 3;
    }

    for (int i = 0; i < array_size; i++)
        printf("%d: %d\n", i, array[i]);

    Node *root1 = NULL;

    // task1: construct a bst from the unsorted array
    printf("=== task1: construct a bst from the unsorted array ===\n");

    for (int i = 0; i < array_size; i++)
    {
        root1 = bstInsert(root1, array[i]);
        displayTree(root1, 0);
    }

    displayTree(root1, 0);
    return 0;
}   

Node *bstInsert(Node *root, int data)
{
    if (root == NULL)
    {
        root = createNode(data);
        if (root == NULL)
            printf("%d not inserted, no memory available.\n", data);
    }
    else if (data < root->data)
        root->left = bstInsert(root->left, data);
    else
        root->right = bstInsert(root->right, data);
    return root;
}

Node *createNode(int data)
{
    Node *aRoot;

    aRoot = malloc(sizeof(Node));
    if (!aRoot)
    {
        printf("Unable to allocate memory for node.\n");
        return NULL;
    }
    aRoot->data = data;
    aRoot->left = NULL;
    aRoot->right = NULL;
    return aRoot;
}

/* helper functions to print a bst; You just need to call displayTree when visualizing a bst */
void padding(char ch, int n)
{
    for (int i = 0; i < n; i++)
        printf("%c%c%c%c", ch, ch, ch, ch);
}

void displayTree(Node *root, int depth)
{
    if (root == NULL) {
        padding (' ', depth);
        printf("-\n");
    }
    else {
        displayTree(root->right, depth+1);
        padding(' ', depth);
        printf ( "%d\n", root->data);
        displayTree(root->left, depth+1);
    }
}

Ok, think about what you want to do in the different tree configurations: 好的,请考虑在不同的树配置中要执行的操作:

  • when the tree is empty -> create a root node 当树为空时->创建根节点
  • when the tree isn't empty -> how do the value to be inserted and the value of the root compare? 当树不为空时->要插入的值和根的值如何比较?
    • above -> insert in the right subtree 上方->插入右侧子树
    • below -> insert in the left subtree 下面->在左侧子树中插入
    • equal -> do nothing (this actually depends on how your assignment tells you to treat duplicates) 相等->不执行任何操作(这实际上取决于您的作业告诉您如何处理重复项)

From this basic algorithm, you should be able to figure out all the corner cases. 通过这种基本算法,您应该能够找出所有极端情况。

A simplified solution (naive insertion with recursion, data input noise removed): 简化的解决方案(天真插入并递归,消除了数据输入噪声):

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

static int nums[] = { 6, 8, 4, 1, 3, 7, 14, 10, 13 }; // instead of the user input

typedef struct _node {
    int value;
    struct _node *left;
    struct _node *right;
} node;

node *node_new(int v)
{
    node *n = malloc(sizeof(*n));
    assert(n);

    n->value = v;
    n->left = NULL;
    n->right = NULL;

    return n;
}

void insert(node **tree, node *leaf)
{
    if (*tree == NULL) {
        *tree = leaf;
    } else if (leaf->value > (*tree)->value) {
        insert(&((*tree)->right), leaf);
    } else {
        insert(&((*tree)->left), leaf);
    }
}

void dump(node *tree, int level)
{
    static const char *pad = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";

    if (tree != NULL) {
        printf("%sSelf: %d\n", pad + 16 - level, tree->value);
        if (tree->left) {
            printf("%sLeft node:\n", pad + 16 - level);
            dump(tree->left, level + 1);
        }
        if (tree->right) {
            printf("%sRight node:\n", pad + 16 - level);
            dump(tree->right, level + 1);
        }
    } else {
        printf("%sEmpty\n", pad + 16 - level);
    }
}

int main()
{
    size_t n = sizeof(nums) / sizeof(*nums);
    int i;
    node *tree = NULL;
    for (i = 0; i < n; i++) {
        insert(&tree, node_new(nums[i]));
    }

    dump(tree, 0);

    // give some work to the kernel
    return 0;
}

You should consider doing this recursively. 您应该考虑递归执行此操作。 Remember that each node is a tree in itself: 请记住,每个节点本身就是一棵树:

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

typedef struct tree_struct {
    int value;
    struct tree_struct* left;
    struct tree_struct* right;
} Tree;

Tree* addToTree(int value, Tree* tree)
{
    if (tree == NULL) {
        tree = malloc(sizeof(Tree));
        tree->value = value;
        tree->left = NULL;
        tree->right = NULL;
    } else {
        if (value < tree->value) {
            tree->left = addToTree(value, tree->left);
        } else {
            tree->right = addToTree(value, tree->right);
        }
    }
    return tree;
}

int main(int argc, char** argv)
{
    Tree* tree = NULL;
    int in;
    while (scanf("%d", &in) != EOF) {
        tree = addToTree(in, tree);
    }

    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM