2013-03-07 6 views
0

C에서 BST를 구현했습니다. 삽입 및 조회가 정상적으로 작동합니다. 그러나 삭제는 루트 노드를 삭제할 때 문제가 있습니다. 루트 노드에 대한 포인터를 해제 할 수 없습니다. 이중 포인터로 전달하면 될 수 있지만 이중 포인터를 사용하지 않고 코드를 간단하게 유지하려고합니다. 여기에는 루트 노드를 가리키는 헤드 포인터가 없습니다. 루트 노드에 헤드 포인터를 사용해야합니까?C에서 이진 검색 트리에서 삭제

#include<stdio.h> 
#include<stdlib.h> 
struct node 
{ 
    int data; 
    struct node* left; 
    struct node* right; 
}; 
struct node* newNode(int data) 
{ 
    struct node* node = malloc(sizeof(struct node)); 
    node->data=data; 
    node->left=NULL; 
    node->right=NULL; 
    return(node); 
} 

static int lookup(struct node* node,int target) 
{ 
    if(node==NULL) 
    { 
     return(0); 
    } 
    else 
    { 
     if(target == node->data) 
     { 
      return(1); 
     } 
     else 
     { 
      if(target < node->data) 
      { 
       return(lookup(node->left,target)); 
      } 
      else 
      { 
       return(lookup(node->right,target)); 
      } 
     } 
    } 
} 


struct node* insert(struct node* node, int data) 
{ 
    if(node==NULL) 
    { 
     return(newNode(data)); 
    } 
    else 
    { 
     if(data < node->data) 
     { 
      node->left =insert(node->left,data); 
     } 
     else 
     { 
      node->right=insert(node->right,data); 
     } 
     return(node); 
    } 
} 

struct node* delete(struct node* node, struct node* pnode, int target) 
{ 
    struct node* rchild; 
    struct node* rchildparent; 
    if(node==NULL) 
    { 
     return(pnode); 
    } 
    else 
    { 
     if(target == node->data) 
     { 
      if(node->left == NULL && node->right == NULL) //leaf node 
      { 
       if(pnode == NULL) //special case deleting the root node 
       { 
        free(node); 
        return(NULL); 
       } 
       if(pnode->left == node) 
       { 
        pnode->left = NULL; 
       } 
       else 
       { 
        pnode->right = NULL; 
       } 
       free(node); 
       return(pnode); 
      } 
      if(node->left ==NULL) //one child 
      { 
       if(pnode == NULL) //deleting root having no left child 
       { 
        struct node* temp = node; 
        node = node->right; 
        free(temp); 
        return(node); 
       } 
       if(pnode->left == node) 
       { 
        pnode->left = node->right; 
       } 
       else 
       { 
        pnode->right = node->right; 
       } 
       free(node); 
       return(pnode); 
      } 
      if(node->right ==NULL) //one child 
      { 
       if(pnode == NULL) //deleting root having no right child 
       { 
        struct node* temp = node; 
        node = node->left; 
        free(temp); 
        return(node); 
       } 
       if(pnode->left == node) 
       { 
        pnode->left = node->left; 
       } 
       else 
       { 
        pnode->right = node->left; 
       } 
       free(node); 
       return(pnode); 
      } 

      //two children case 
      rchild = node->right; 
      rchildparent=node; 
      while(rchild->left != NULL) 
      { 
       rchildparent=rchild; 
       rchild = rchild->left; 
      } 
      node->data=rchild->data; 
      if(rchildparent == node) 
      { 
       //rchildparent->right=rchild->right; 
       node->right=rchild->right; 
      } 
      else 
      { 
       //rchildparent->left=NULL; 
       rchildparent->left=rchild->right; 
      } 
      free(rchild); 
      if(pnode ==NULL) //root node 
      { 
       return(node); 
      }   
      return(pnode); 
     } 
     else 
     { 
      if(target < node->data) 
      { 
       delete(node->left,node,target); 
       return(node); 
      } 
      else 
      { 
       delete(node->right,node,target); 
       return(node); 
      } 
     } 

    } 

} 
void printinorder(struct node* node) 
{ 
    if(node == NULL) 
    { 
     return; 
    } 
    printinorder(node->left); 
    printf("%d\t",node->data); 
    printinorder(node->right); 
} 
int main() 
{ 
    clock_t start,end; 
    struct node* root = newNode(3); 
    insert(root,7); 
    insert(root,7); 
    insert(root,7); 
    printinorder(root); 
    printf("\n"); 
    root = delete(root,NULL,6); 
    printinorder(root); 
    printf("\n"); 
} 

편집 : 이 modifiable lvalue 제안 @에 따라 코드를 수정했습니다. 이제 삭제 논리를 개선 할 수있는 방법이 있습니까?

+0

나는 아무 문제가 newNode''함수에서'malloc'와 함께이없는 것 같아요. 문제는 루트 노드에 대한 포인터의 로컬 사본을 해제하는'delete' 함수에 있습니다. – arunmoezhi

+0

'delete' 함수에 전달되어야하는 특별한 ROOT 포인터가 필요할 것입니다. 또 다른 해결책은 비 재귀적인'delete' 함수를 작성하여 새로운 루트가 될'node *'를 반환하도록하는 것입니다. – uba

+1

@ Koushik 무슨 말씀 이세요? malloc이 실패 할 때 잠재적 인 NULL 역 참조를 제외하고는 newNode가 좋습니다. – Sebivor

답변

1

머리 부분 노드를 삭제하고 메인 기능에서 다음과 같이 헤드를 관리합니다. root = delete(root, NULL, 10);과 같은 작업을하고, 삽입 할 경우에도 동일한 작업을 수행합니다 : root = insert(root,/*...*/);. ..

+0

고마워. 이것은 간단하고 우아합니다. 변경을했는데 루트를 삭제하는 경우에 문제가 없습니다. – arunmoezhi

+0

내가 가장 좋아하는 것은 다른 사람들에게 '머리'가 실제로 바뀔 수 있다는 것이 분명하다는 것입니다. 나는'head '가 바뀔 수있는 어떤 함수 (링크 된리스트, 큐 등등)에서 이것을하기를 좋아한다. 그렇게하면 그룹 프로젝트와 상업 환경에서 포인터가 매달 리는 문제가 줄어들 것입니다. 이 경우 트리 균형을 조정할 수있는 기회이기도합니다. – Sebivor

+0

내가 생각하기에는 여전히 내가'delete'에서 맘에 들지 않는다고 생각하는 것은 루트의 특별한 경우가 삭제되는지를 확인할 때마다입니다. 성능 향상을 위해 어떻게 든 피할 수 있습니까? – arunmoezhi

0

개인 데이터 노드 삭제 (데이터 노드 루트, INT의 dValue) {

DataNode temp=null; 
if(root!=null){ 
    if(dValue<root.value){ 
     root.left=delete(root.left,dValue); 
    } 
    else if(dValue>root.value){ 
     root.right=delete(root.right,dValue); 
    } 
    else{ 
      if(root.left==null){ 
       temp=root.right; 
       root.right=null; 
       return temp; 
      } 
      else if(root.right==null){ 
       temp=root.left; 
       root.left=null; 
       return temp; 
      } 

      temp=MinBST(root.right); 
      root.value=temp.value; 
      //deleting inorder successor 
      root.right=null; 
    } 
} 
return root; 

}

개인 데이터 노드 MinBST (데이터 노드 루트) {

if(root!=null){ 
    while(root.left!=null){ 
     root=root.left; 
    } 
} 
return root; 

} 이진 트리에서 노드의 삭제를위한 링크를 통해

이동

https://www.youtube.com/watch?v=YK3tLMYk3nk

0
//c tree 
#include<stdio.h> 
#include<conio.h> 
struct tree_node 
{ 
    struct tree_node*right,*left; 
    int data; 
}; 
struct tree_node*savetemp=NULL; 
struct tree_node* del(struct tree_node*,int); 
struct tree_node* insert(struct tree_node*,int); 
struct tree_node* travel(struct tree_node*,struct tree_node*); 
void inorder(struct tree_node *); 
int height(struct tree_node*); 
int noOfNode(struct tree_node *); 
void main() 
{ 
    struct tree_node* root=NULL; 
    int item,cho; 
    clrscr(); 
    do 
    { 
     printf("Enter your choice\n"); 
     printf("1.insert 2.delete 3.display 4.no of nodes 5.height 6.exit\n"); 
     scanf("%d",&cho); 
     switch(cho) 
     { 
      case 1:{ 
       printf("Enter element to insert\n"); 
       scanf("%d",&item); 
       root=insert(root,item); 
      } 
      break; 
      case 2:{ 
       printf("Enter element to delete\n"); 
       scanf("%d",&item); 
       root=del(root,item); 
       if(savetemp!=NULL)//condition for any break link is present to insert or not 
       travel(root,savetemp);//to insert break link during insertion 
      } 
      break; 
      case 3:{ 
       printf("inorder travel\n"); 
       inorder(root); 
      } 
      break; 
      case 4:{ 
       printf("No of nodes are: %d\n",noOfNode(root)); 
      } 
      break; 
      case 5: 
      printf("height of tree %d",height(root)); 
      break; 
      case 6: 
      printf("Exiting"); 
      break; 
      default : printf("wrong cho\n"); 
     } 
    }while(cho!=6); 
    getch(); 
} 
void inorder(struct tree_node *root) 
{ 
    if (root != NULL) 
    { 
    inorder(root->left); 
    printf("%d \n", root->data); 
    inorder(root->right); 
    } 
} 
struct tree_node* insert(struct tree_node*root,int item) 
{ 
    if(root==NULL) 
    { 
     struct tree_node* temp; 
     temp=(struct tree_node*)malloc(sizeof(struct tree_node)); 
     temp->left=NULL; 
     temp->right=NULL; 
     temp->data=item; 
     root=temp; 
    } 
    else 
    { 
      if(root->data<item) 
      { 
       root->right=insert(root->right,item); 
      } 
      else 
      { 
       root->left=insert(root->left,item); 
      } 
    } 
    return(root); 
} 
struct tree_node* del(struct tree_node*root,int item) 
{ 
    if(item==root->data) 
    { 
     if(root->left==NULL&&root->right==NULL) //no child 
     { 
      root=NULL; 

     } 
     else if(root->left==NULL||root->right==NULL) //one child 
     { 
      if(root->left!=NULL) //left child 
      { 
       root=root->left; 
      } 
      else    //right child 
      { 
       root=root->right; 
      } 
     } 
     else if(root->left!=NULL&&root->right!=NULL) //both child 
     { 
      struct tree_node* temp; 
      savetemp=root->right->left; 
      temp=root; 
      root=root->right; 
      root->left=temp->left; 
     } 
    } 
    else 
    { 
      if(root->data<item) 
      { 
       root->right=del(root->right,item); 
      } 
      else 
      { 
       root->left=del(root->left,item); 
      } 
    } 
    return(root); 
} 
struct tree_node* travel(struct tree_node*root,struct tree_node*savetemp) 
{ 
    if (savetemp != NULL) 
    { 
     insert(root,savetemp->data); 
     travel(root,savetemp->left); 
     travel(root,savetemp->right); 
    } 
    return(root); 
} 
int height(struct tree_node*root) 
{ 
    int lheight,rheight; 
    if(root==NULL) 
    { 
     return(-1); 
    } 
     else 
    { 
     lheight=height(root->left); 
     rheight=height(root->right); 
    } 
    if(lheight>rheight) 
    { 
     return(lheight+1); 
    } 
    else 
    { 
     return(rheight+1); 
    } 
} 
int noOfNode(struct tree_node *root) 
{ 
static int count=0; 
    if (root != NULL) 
    { 
    noOfNode(root->left); 
    count=count+1; 
    noOfNode(root->right); 
    } 
    return(count); 
} 
+0

더 자세히 알려주십시오. –

+0

이 코드 블록에 몇 가지 설명을 추가하십시오. –

+0

다시 체크 아웃 나는 뭔가를 바꿨다 ......... –