2017-11-28 20 views
0

A(左)とB(右)がすでにいっぱいの場合、バイナリツリーにノードを追加するにはどうすればよいですか?バランスのとれたツリーを作成するだけです。しかし、ツリーにデータを追加する方法を理解することはできません。どんな助けでも大歓迎です。Cでバイナリツリーにノードを追加する方法は?

ありがとうございます。

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

struct node 
{ 
    char *titel; 
    struct node *A; 
    struct node *B; 
}; 

void display(struct node *leaf) 
{ 
    if (leaf != NULL) 
    { 
     display(leaf->A); 
     printf("%s\n",leaf->titel); 
     display(leaf->B); 
    } 
} 

struct node *insert(char* titel, struct node **leaf) 
{ 
    if (*leaf == 0) 
    { 
     *leaf = (struct node*)malloc(sizeof(struct node)); 
     (*leaf)->titel = malloc(strlen(titel)+1); 
     strcpy((*leaf)->titel,titel); 
     (*leaf)->A = NULL; 
     (*leaf)->B = NULL; 
    } 
    else if ((*leaf)->A == NULL) 
    { 
     (*leaf)->A = insert(titel,&(*leaf)->A); 
    } 
    else if ((*leaf)->B == NULL) 
    { 
     (*leaf)->B = insert(titel,&(*leaf)->B); 
    } 
    //WHAT TO ADD HERE TO CREATE ANOTHER NODE? 
    return(*leaf); 
} 

int main(int argc, char const *argv[]) 
{ 
    struct node *root = NULL; 
    insert("root",&root); 
    insert("chapter_1A",&root); 
    insert("chapter_1B",&root); 
    insert("chapter_2A",&root); 
    insert("chapter_2B",&root); 
    insert("chapter_3A",&root); 
    display(root); 
    return 0; 
} 

出力はバランスのとれたバイナリツリーのようにする必要があります。印字する必要はありませんが、メモリにそのように保存してください。

実際の出力:

chapter_1A 
root 
chapter_1B 

     root 
       /  \ 
      chapter_1A chapter_1B 
     / \ / \ 
     ch_2A ch_2B ch_3A ch_3B 
       and so on. 
+1

ツリーがいっぱいになることはありますか? –

+0

正確な問題は何ですか?あなたはどんなアウトプットを受け取り、どんなアウトプットを期待していますか? –

+0

私は自分のツリーに別のノードを追加する方法を知らない。それは私の問題です。私は、ルートノードを作成して、次にルートの左側を塗り、次に右側を塗りつぶします。しかし、左サイドノードまたは右サイドノードから別のブランチを作成する方法はわかりません。それは私の正確な問題です。 編集:入力はメインに表示されます。 出力は、左から右に向かって開始するツリーでなければなりません。 ルート /\ ch_A1 ch_B1 /\/\ A2 B2 A3 B3 ちょうど平衡二分探索木のように。 –

答えて

3

A(左)とB(右)がすでに満杯であれば、私は私のバイナリツリーにノードを追加するにはどうすればよいですか?

「フル」とは、両方の子ノード自体に2つの子があることを意味します。この場合、子ノードの子ノードのいずれかに新しいノードを追加する必要があります。通常は、再帰関数を使用してこれを行います。これにより、子どもの子も "完全"なようなケースを正しく処理できるようになります。

は、私はちょうど(「バランス」は、それ自体は、いくつかのものを意味することに注意してください。例えば、「高さのバランス」と「重量バランスの取れた」木がある

バランスが取れているツリーを作成する必要があります。どちらを指定するかは指定しないでください)。

質問は、(フル)子が新しいノードを右または左に追加するかどうかです。 1つの選択肢は、各ノードの子孫の総数を保持し、常に子ノードに追加することです。

ツリー内のノードの総数をカウントし、その番号のビットを使用して(最初の1ビットを無視して)、新しいノードを挿入する場所を決定します。あなたは5つのノードでツリーを持っている場合たとえば、新しいノードを追加するには

    A 
      B   C 
     D E 

、バイナリで110である、6にノードカウントをインクリメント。最初の文字は無視してください1;次の1を「右に」(Cに)、「0」を「左に」(Cの左の子として挿入するように指示する)と解釈します。あなたが値を返す必要がないので、私はvoidに戻り値の型を変更し

void insert(char* titel, struct node **leaf, int nodeCount, int bitPos) 
{ 
    if (*leaf == 0) 
    { 
    *leaf = (struct node*)malloc(sizeof(struct node)); 
    (*leaf)->titel = malloc(strlen(titel)+1); 
    strcpy((*leaf)->titel,titel); 
    (*leaf)->A = NULL; 
    (*leaf)->B = NULL; 
    } 
    else 
    { 
    int currentBit = (nodeCount >> bitPos) & 1; 
    if (currentBit == 0) { 
     // insert to left 
     insert(titel, &((*leaf)->A), nodeCount, bitPos - 1); 
    } 
    else 
    { 
     // insert to right 
     insert(titel, &((*leaf)->B), nodeCount, bitPos - 1); 
    } 
    } 
} 

お知らせ:あなたのコードは次のようになります。私は最初の計算の値をbitPosのままにしておきます(覚えておいてください:最高位の位置は1ビットから1を引いたものです)。

ツリーから要素を削除する必要がある場合は、その要素を再バランスする方法を見つける必要があります。

挿入と削除の両方をサポートするバランスのとれたツリーを維持するためのいくつかのデータ構造とアルゴリズムがあります。例えば、red-black treesおよびAVL treesを参照してください。これらは通常順序付けされたツリーに使用されますが、順序付けられていないバランスのとれたツリーに適合させるのは簡単です。

+0

[RedBlackTree - MIT](http://web.mit.edu/~emin/www.old/source_code/red_black_tree/)と[AVL Tree - ZenTut](http: //www.zentut.com/c-tutorial/c-avl-tree/)。 (Linuxカーネルにも両方の良い実装が含まれていますが、かなりの数のマクロを使用しています) –

+0

ありがとう。しかし、私がbitPosの値を計算する必要なしに高さの平衡した二分木を作成する方法はありませんか? –

+0

@GerhardHaidはい、私がすでに言ったように:AVLツリーまたはRed-Blackツリーを使用できます。しかし、私は 'bitPos'の計算がなぜ問題になるのか分かりません(もしあなたがそれをやる方法がわからないのであれば、適切な答えがまだ存在しなければ検索するか質問をしてください)。 – davmac

関連する問題