二分探索木の削除について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
sato10

二分探索木の削除について

#1

投稿記事 by sato10 » 8年前

二分探索木の削除について
削除の方法の考え方は分かったのですが、
parentの親のポインタをparentpで表そうとしたらよくわからなくなってしまいました。
教えてもらえないでしょうか

コード:

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

#define Name_Len 32
#define NumOfPhone 14
#define max_data 100000


typedef struct Node{
  char name[Name_Len];
  char phone[NumOfPhone];
  struct Node *left;
  struct Node *right;
}node;

int input_data(char file_name[], node **root, node *data){
  int i = 0;
  node *parent;
  FILE *fp;
  fp = fopen(file_name, "r");
  if(fp == NULL){
    printf("%sのファイルが開けません。\n",file_name);
    exit (0);
  }
  else{
    while (fscanf(fp, "%s%s", (data+i)->name, (data+i)->phone) == 2){
      (data+i)->left = NULL;
      (data+i)->right = NULL;
      if (*root == NULL){
        *root = data+i;
      }
      else{
        parent = *root;
        while(1){
          if(strcmp((data+i)->name, parent->name) < 0){
            if(parent->left == NULL){
              parent->left = (data+i);

              break;
            }
            else{
              parent = parent->left;
            }
          }
          else{
            if(parent->right == NULL){
              parent->right = (data+i);
              break;
            }
            else
              parent = parent->right;
            }
          }
        }
      }
      i++;
    }
  }
  return i;
}

int delete_data(char scname[], node **root){
  node *parent, *parentp;       //parentpは*parentの親を示す
  node *tmp;
  parent = *root;
  while(1){
    if(strcmp(scname, parent->name) == 0) break;
    if(strcmp(scname, parent->name) < 0){
      if(parent->left == NULL){
        return ;
      }
      parent = parent->left;
    }
    else{
      if(parent->right == NULL){
        return ;
      }
      parent = parent->right;
    }
    return (parent);
  }



  while(parent != NULL){
    if(strcmp(scname, parent->name) < 0){
      parent = parent->left;
    }
    else{
      parent = parent->right;
    }
  }

 if(parent->right == NULL && parent->left == NULL){ //子を持たない時
    if(parent == *root){
      *root = NULL;
    }
    else{
      if(parentp -> left == parent)
        parentp -> left = NULL;
      else
        parentp ->right = NULL;
    }
  }


  if(parent->right == NULL && parent->left != NULL){  //削除ノードが左子をもつ時
    if(parent == *root){
      *root = parent-> left;
      *root ->parentp = NULL;
    }
    else {
      if(parentp -> left == parent)
        parentp -> left = parent->left;
      else
        parentp ->right = parent->left;
      parent->left ->parentp = parentp;
    }
  }

  if(parent->right != NULL && parent->left == NULL){  //削除ノードが右子をもつ時
    if(parent== *root){
      *root = parent->right;
      *root -> parentp = NULL;
    }
    else {
      if(parentp -> left == parent)
        parentp -> left = parent -> right;
      else
        parentp -> right = parent->right;
      parent -> right -> parentp = parent -> parentp;
    }
  }

  if(parent->right != NULL && parent->left != NULL){ //両方に子をもつ時
    tmp = parent->right; //右の子の左の子をたどる
    while(tmp ->left){
      tmp = tmp ->left;

    parent->right = NULL;
    parent = tmp;
    }
  }
}

int main(void){
  int i;
  int select = 0;
  char file_name[64];
  char scname[Name_Len];
  node data[max_data];
  node *root, *parent;
  printf("ファイル名を入力してください。");
  scanf("%s", file_name);
  input_data(file_name, &root, &data[0]);

  printf("削除する名前を入力してください。\n");
  scanf("%s", scname);
  deleat_data(scname);

  return 0;
}

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 二分探索木の削除について

#2

投稿記事 by みけCAT » 8年前

まず最初に、main関数で使用されている関数deleat_dataの定義が(少なくともここには)ありません。
delete_dataの間違いではないでしょう?

次に、戻り値がintであるdelete_data関数において、
返り値を指定しないreturn文があったり、return文を通らずに戻ることがあったりするのはあまりよくないですね。
きちんとdelete_data関数内の全てのreturn文で返り値を指定し、
最後にも返り値を指定するreturn文を追加するといいでしょう。
オフトピック
ポインタを処理系定義の方法で整数に変換して返すというのも不自然な仕様だと思いますが、
プログラムとして間違いとは言えないでしょう。
そして、このプログラムではそのノードにくる直前にいるノードがそのノードの親のはずなので、
parentpにはparentを更新するように直前のparentの値を代入するといいでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

sato10

Re: 二分探索木の削除について

#3

投稿記事 by sato10 » 8年前

parentpにはparentを更新するように直前のparentの値を代入するといいでしょう。
ここをどう書けばいいのかわかりませんでした、
直前のparentの値はどう書けばいいのでしょうか

閉鎖

“C言語何でも質問掲示板” へ戻る