1

今夜午後 8 時 CDT が期限のプログラミング クラスの割り当てがあり、これに問題があります。ファイルを読み取って、次の番号のリストを取得します。

9 30 20 40 35 22 48 36 37 38

それらを配列に配置し (簡単です)、C を使用してこれらを二分探索木に読み込みます。リストの最初の数字は、ツリー内の要素の数です。残りは次の構造体に配置されます。

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

私は最初の部分をパットしたと思います。fscanf を使用して (私はこの方法を使用することを選択しませんでした。fgets の方が好きです)、配列の各メンバーで挿入関数を呼び出し、挿入関数内で「createNode」関数を呼び出します。

問題は、BST に 1 人のメンバーしか入れていないことです。さらに、BST は条件を満たさなければなりませんnode->left->data <= node->data < node->right->data...つまり、ノードはツリー内で順番に並んでいる必要があります。

これが私がこれまでに持っているものです:

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

maincreateNodedisplayTree、そしてpadding大丈夫だと思います。bstInsert困っているところです。有効なツリーを作成するために物事を注文する方法がわかりません。

編集:

bstInsert を編集し、さらにロジックを挿入しました。ツリーにもっと多くの葉が表示されるはずですが、残念ながら「30」という数字しか表示されません。こちらが新機能。

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

4 に答える 4

1

新しく作成されたノードポインタをツリーの正しい部分に割り当てる必要があります。このコードはそれを行います。重要な変更は、からの戻り値をbstInsert()正しく使用することです。その他の変更は表面的なものです。入力配列を印刷してチェックしたことに注意してください。また、BSTを作成するときに印刷することも賢明です。

feof()ループ制御条件として使用しないでください。ループ制御として使用する場合はほぼ必ず間違っていますが、少なくとも次の入力操作も確認する必要があります。私は自分の時代にたくさんのプログラムを書きました。私はほとんど使用したことがありませんfeof()(自分のコードで2つの場所を見つけました。どちらの場合も、入力が失敗した後の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);
    }
}
于 2012-10-28T21:41:21.830 に答える
0

さて、さまざまなツリー構成で何をしたいのか考えてみてください。

  • ツリーが空の場合->ルートノードを作成します
  • ツリーが空でない場合->挿入される値とルートの値はどのように比較されますか?
    • 上->右側のサブツリーに挿入
    • 下->左側のサブツリーに挿入
    • 等しい->何もしない(これは実際には、割り当てが重複を処理するように指示する方法によって異なります)

この基本的なアルゴリズムから、すべてのコーナーケースを理解できるはずです。

于 2012-10-28T21:27:47.470 に答える
0

単純化されたソリューション(再帰を伴う単純な挿入、データ入力ノイズの除去):

#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;
}
于 2012-10-28T21:49:02.330 に答える
0

これを再帰的に行うことを検討する必要があります。各ノードはそれ自体がツリーであることを思い出してください。

#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;
}
于 2012-10-28T22:15:08.703 に答える