二叉查找树删除操作

二叉查找树中,最复杂的操作就是删除操作。对于叶子节点,直接删除即可。对于一颗子树的节点,用子树取代原节点即可。对于拥有两颗子树的节点,首先用右子树最小的节点取代源节点,再递归删除此最小节点。

具体代码如下所示:

  1. package com.Algorithm.Tree;  
  2. import java.util.*;  
  3. import java.io.*;  
  4. /* 
  5.  * author:Tammy Pi 
  6.  * function:二叉查找树 
  7.  */  
  8. public class BiSearchTree {  
  9.   
  10.     public TreeNode root=null;  
  11.     private Scanner scanner=null;  
  12.       
  13.     public BiSearchTree()  
  14.     {  
  15.         scanner=new Scanner(System.in);  
  16.     }  
  17.     public TreeNode getRoot() {  
  18.         return root;  
  19.     }  
  20.     public void setRoot(TreeNode root) {  
  21.         this.root = root;  
  22.     }  
  23.     public Scanner getScanner() {  
  24.         return scanner;  
  25.     }  
  26.     public void setScanner(Scanner scanner) {  
  27.         this.scanner = scanner;  
  28.     }  
  29.       
  30.     public void createTree()  
  31.     {  
  32.         this.root=createTree(this.root);  
  33.     }  
  34.     public void midTraverse()  
  35.     {  
  36.         midTraverse(this.root);  
  37.     }  
  38.     //中序遍历,相当于排序   
  39.     public void midTraverse(TreeNode root)  
  40.     {  
  41.         if(root!=null)  
  42.         {  
  43.             midTraverse(root.getLchild());  
  44.             System.out.print(root.getData()+" ");  
  45.             midTraverse(root.getRchild());  
  46.         }  
  47.     }  
  48.     //建立二叉查找树   
  49.     public TreeNode createTree(TreeNode root)  
  50.     {  
  51.         String str=scanner.next();  
  52.         int n=Integer.parseInt(str);  
  53.           
  54.         for(int i=0;i<n;i++)  
  55.         {  
  56.             String data=scanner.next();  
  57.             if(root==null)  
  58.             {  
  59.                 root=new TreeNode(data);  
  60.             }  
  61.             else   
  62.             {  
  63.                 TreeNode node=new TreeNode(data);  
  64.                 TreeNode x=root,y=root;  
  65.                   
  66.                 while(x!=null)  
  67.                 {  
  68.                     if(x.getData().compareTo(node.getData())>0)  
  69.                     {  
  70.                         y=x;  
  71.                         x=x.getLchild();  
  72.                     }  
  73.                     else   
  74.                     {  
  75.                         y=x;  
  76.                         x=x.getRchild();  
  77.                     }  
  78.                 }  
  79.                 if(y.getData().compareTo(node.getData())>0)  
  80.                 {  
  81.                     y.setLchild(node);  
  82.                 }  
  83.                 else  
  84.                 {  
  85.                     y.setRchild(node);  
  86.                 }  
  87.             }  
  88.         }//for i   
  89.           
  90.         return root;  
  91.     }//createTree   
  92.     //查找最小的节点   
  93.     public TreeNode findMin(TreeNode node)  
  94.     {  
  95.         TreeNode x=node;  
  96.         while(node!=null)  
  97.         {  
  98.             x=node;  
  99.             node=node.getLchild();  
  100.         }  
  101.         return x;  
  102.     }  
  103.     public void testRemove()  
  104.     {  
  105.         root.setRchild(remove(root.getRchild(),root.getRchild()));  
  106.         System.out.print("删除节点后,中序遍历结果为:");  
  107.         midTraverse();  
  108.     }  
  109.     //删除节点   
  110.     //node为待删除节点   
  111.     public TreeNode remove(TreeNode node,TreeNode subTree)  
  112.     {  
  113.         if(subTree==null)  
  114.         {  
  115.             return null;  
  116.         }  
  117.           
  118.         int state=node.getData().compareTo(subTree.getData());  
  119.         if(state<0)  
  120.         {  
  121.             node.setLchild(remove(node,subTree.getLchild()));  
  122.         }  
  123.         else if(state>0)  
  124.         {  
  125.             node.setRchild(remove(node,subTree.getRchild()));  
  126.         }  
  127.         else if(node.getLchild()!=null&&node.getRchild()!=null)  
  128.         {  
  129.             TreeNode temp=findMin(node.getRchild());  
  130.             node.setData(temp.getData());  
  131.             node.setRchild(remove(temp,node.getRchild()));  
  132.         }  
  133.         else  
  134.         {  
  135.             node=(node.getLchild()!=null?node.getLchild():node.getRchild());  
  136.         }  
  137.         return node;  
  138.     }  
  139.     //用于测试的主函数   
  140.     public static void main(String[] args)  
  141.     {  
  142.         BiSearchTree biTree=new BiSearchTree();  
  143.         biTree.createTree();  
  144.         System.out.println("查找二叉树建立完成!");  
  145.         System.out.print("中序遍历结果为:");  
  146.         biTree.midTraverse();  
  147.         System.out.println();  
  148.         biTree.testRemove();  
  149.     }  
  150. }  

 

在本练习中,我们讨论从二叉查找树删除节点问题。删除算法不像插入算法那么简单明了。删除一个值可能有三种不同的情况————该值包含在一个叶子节点中(没有子节点),该值包含在只有一个子节点中或者包含在两个子节点的节点中。

如果该项在叶节点中,直接删除该节点,将其父节点指向它的指针置为空。

如果该项包含在只含一个子节点的节点中,把父节点的指针指向它的子节点再删除这个数据项,就是由它的子节点替代该节点的位置。最后一种情况是最难的。当要删除的节点含有2个子节点时,由另一个叶子节点代替它的位置

编写一个二叉树的成员函数deleteNode,以树的根节点指针和要删除的值为参数。该函数需要找到包含该值的节点,使用上面讨论的算法将该节点删除。该函数还要打印一条信息以表明该节点被删除。当删除完成后,使用中序、前序和后序遍历来确认该节点是否已被正确删除。

///BinSTree.h//

#pragma once

#include <iostream>

#include <stdio.h>

using namespace std;

class BinSTree;

class TreeNode

{

public:

         friend class BinSTree;

         TreeNode(char item, TreeNode *lptr = NULL, TreeNode *rptr = NULL                            ):contents(item),left(lptr),right(rptr){ }

private:

         char contents;         //节点值

         TreeNode *left;         //左孩子

         TreeNode *right;        //右孩子

};

typedef TreeNode* LPTreeNode;

class BinSTree

{

public:

         BinSTree(void);

         ~BinSTree(void);

         void CreatBinSTree(LPTreeNode &tree);   //创建新树

         void MiddleRead(TreeNode *t);     //中序遍历

         void FirstRead(TreeNode *t);     //前序遍历

          void LastRead(TreeNode *t);      //后序遍历

         void Find(TreeNode *tree,char i);    //查找是否存在值为i的节点

         LPTreeNode Search(LPTreeNode &tree);     //

         void DeleteNode(LPTreeNode &tree,char i); //删除值为i的节点

         TreeNode *node;         //根节点

private:

         bool tj;

};

BinSTree.cpp/

#include "BinSTree.h"

BinSTree::BinSTree(void)

{

         tj=false;

}

BinSTree::~BinSTree(void)

{

}

void BinSTree::CreatBinSTree(LPTreeNode &tree)

{

         char c;

         scanf("%c",&c);         //获得一个节点值

         if(c==' ')

         {

                  tree = NULL;

         }

         else

         {

                  tree = new TreeNode(c);      //生成一个新节点

                  CreatBinSTree(tree->left);     //生成左子树

                  CreatBinSTree(tree->right);     //生成右子树

         }

}

void BinSTree::MiddleRead(TreeNode *t)

{

         if(node == NULL)

         {

                  cout<<"空树,无法遍历!"<<endl;

                  return;

         }

         if(t!=NULL)

         {

                  MiddleRead(t->left);

                  cout<<t->contents<<" ";

                  MiddleRead(t->right);

          }

}

void BinSTree::FirstRead(TreeNode *t)

{

         if(node == NULL)

         {

                  cout<<"空树,无法遍历!"<<endl;

                  return;

         }

         if(t!=NULL)

         {

                  cout<<t->contents<<" ";

                  MiddleRead(t->left);

                  MiddleRead(t->right);

         }

}

void BinSTree::LastRead(TreeNode *t)

{

         if(node == NULL)

         {

                  cout<<"空树,无法遍历!"<<endl;

                  return;

         }

         if(t!=NULL)

         {

                  MiddleRead(t->left);

                  MiddleRead(t->right);

                  cout<<t->contents<<" ";

         }

}

void BinSTree::Find(TreeNode *tree,char i)

{

         if(tree!=NULL)

         {

                  if(tree->contents==i)

                  {

                           tj=true;

                           return;

                  }

                  if(tree->left!=NULL)

                  {

                           if(tree->left->contents == i)

                           {

                                    tj=true;

                                    return;

                           }

                  }

                  if(tree->right!=NULL)

                  {

                           if(tree->right->contents == i)

                           {

                                    tj=true;

                                    return;

                           }

                  }

         Find(tree->left,i);

         Find(tree->right,i);

         }

}

LPTreeNode BinSTree::Search(LPTreeNode &tree)

{

         if(tree!=NULL)

         {  

                  if(tree->left->left==NULL && tree->left->right==NULL)

                  {

                           return tree->left;

                   }

         else if(tree->right->left==NULL && tree->right->right==NULL)

         {

                  return tree->right;

         }

         return Search(tree->left);

         return Search(tree->right);

         }

void BinSTree::DeleteNode(LPTreeNode &tree,char i)
{
         Find(tree,i);
         if(!tj)
         {
                  cout<<"无此节点!"<<endl;
                  return;
         }
         if(tree!=NULL)
         {
                  if(node->contents == i)
                  {
                           if(node->left == NULL && node->right == NULL)
                           {
                                    delete node;
                                    node=NULL;
                                     cout<<"已删除节点,当前树为空"<<endl;
                                    return;
                           }
                           else if(node->left != NULL && node->right == NULL)
                           {
                                    TreeNode *p = node;
                                    TreeNode *d = new TreeNode(Search(node)->contents);
                                    d->left = tree->left;
                                    d->right = NULL;
                                     node = d;
                                    delete p;
                                    cout<<"值为"<<i<<"的节点已被删除"<<endl;
                           }
                            else if(node->right != NULL && node->left == NULL)
                           {
                                    TreeNode *p = node;
                                    TreeNode *d = new TreeNode(Search(node)->contents);
                                    d->left = NULL;
                                    d->right = tree->right;
                                    node = d;
                                    delete p;
                                    cout<<"值为"<<i<<"的节点已被删除"<<endl;
                           }
                           else
                            {
                                    TreeNode *p = node;
                                    TreeNode *d = new TreeNode(Search(node)->contents);
                                    d->left = tree->left;
                                     d->right = tree->right;
                                     node = d;
                                    delete p;
                                    cout<<"值为"<<i<<"的节点已被删除"<<endl;
                            }
                  }
                   if(tree->left!=NULL)
                   {
                           if(tree->left->contents == i)
                           {
                                    if(tree->left->left == NULL && tree->left->right != NULL)
                                    {
                                             TreeNode *p = tree->left;
                                              tree->left = tree->left->right;
                                             delete p;
                                             cout<<"值为"<<i<<"的节点已被删除"<<endl;
                                    }
                                    else if(tree->left->left == NULL && tree->left->right == NULL)
                                    {
                                             delete tree->left;
                                             tree->left = NULL;
                                             cout<<"值为"<<i<<"的节点已被删除"<<endl;
                                    }
                                    else if(tree->left->left != NULL && tree->left->right == NULL)
                                     {
                                             TreeNode *p = tree->left;
                                             tree->left = tree->left->left;
                                             delete p;
                                             cout<<"值为"<<i<<"的节点已被删除"<<endl;
                                    }
                                    else if(tree->left->left != NULL && tree->left->right != NULL)
                                     {
                                             TreeNode *p = tree->left;
                                             TreeNode *d = new TreeNode(Search(node)->contents);
                                             d->left = tree->left->left;
                                             d->right = tree->left->right;
                                            tree->left = d;
                                             delete p;
                                    }
                                    return;
                           }
                  }
                   if(tree->right!=NULL)
                  {
                           if(tree->right->contents == i)
                           {
                                    if(tree->right->left == NULL && tree->right->right == NULL)
                                    {
                                             delete tree->right;
                                             tree->right = NULL;
                                             cout<<"值为"<<i<<"的节点已被删除"<<endl;
                                    }
                                    else if(tree->right->left != NULL && tree->right->right == NULL)
                                    {
                                             TreeNode *p = tree->right;
                                              tree->right = tree->right->left;
                                             delete p;
                                             cout<<"值为"<<i<<"的节点已被删除"<<endl;
                                    }
                                    else if(tree->right->left == NULL && tree->right->right != NULL)
                                    {
                                             TreeNode *p = tree->right;
                                             tree->right = tree->right->right;
                                             delete p;
                                             cout<<"值为"<<i<<"的节点已被删除"<<endl;
                                     }
                                    else if(tree->right->left != NULL && tree->right->right != NULL)
                                    {
                                             TreeNode *p = tree->right;
                                             TreeNode *d = new TreeNode(Search(node)->contents);
                                              d->left = tree->right->left;
                                             d->right = tree->right->right;
                                             tree->right = d;
                                             delete p;
                                     }
                                    return;
                           }
                  }
                  DeleteNode(tree->left,i);
                  DeleteNode(tree->right,i);
         }
}

 

 

 

 

总体思想:分多种情况讨论

1.被删除节点没有子树的情况,直接删除,并修改对应父节点的指针为空。

2.对于只有一个子树的情况,考虑将其子树作为其父节点的子树,关于是左还是右,根据被删除的节点确定。

3.最复杂的是有两个子数的情况,可以考虑两种方法,都是同样的思想:用被删除节点A的左子树的最右节点或者A的右子树的最左节点作为替代A的节点,并修改相应的最左或最右节点的父节点的指针,修改方法类似2 ,不做细致讨论

 

/*************二叉树的节点的删除***********/

/*********该程序描述了从递归建立二叉树到查找*********/
/*********以及删除的全过程,也算是对前面几个*********/
/*********程序的联习与总结***************************/
#include<stdio.h>
#include<stdlib.h>

#define Maxsize 16

//定义二叉树节点
struct treenode
{
 int data;
 struct treenode* left;
 struct treenode* right;
};
typedef treenode Node;
typedef Node* btree;

//递归建立二叉树
btree create_btree(int* nodelist,int postion)
{
 btree newnode;
 
 if(nodelist[postion]==0||postion>=Maxsize)
     return NULL;
 else
 {
  newnode=(btree) malloc(sizeof(Node));
  newnode->data=nodelist[postion];
  newnode->left=create_btree(nodelist,postion*2);
  newnode->right=create_btree(nodelist,postion*2+1);
  return newnode;
 }
}

/********查找二叉树的节点********/
btree search(btree root,int node)
{
 btree point;
 point=root;
 if(point==NULL)
  return root;
 else
  if(point->data==node)
   return point;
  else
   if(point->data>node)
    search(point->left,node);
   else
    search(point->right,node);
}

/********第二种查找方法,记录其父节点的值********/
btree binary_search(btree point,int node,int *postion)
{
 btree parent;

 parent=point;
 *postion=0;

 while(point!=NULL)
 {
  if(point->data==node)
   return parent;
  else
  {
   parent=point;
   if(point->data>node)
   {
    point=point->left;
    *postion=-1;

   }
   else
   {
    point=point->right;
    *postion=1;
   }
  }

 }
 return NULL;

}

/**********删除二叉树节点的操作***********/
btree deletenode(btree root,int node)
{
 btree parent;
 btree point;
 btree child;
    int postion;


 parent=binary_search(root,node,&postion); 
 //二叉树为空的情况
   if(parent==NULL)
  return root;
   else
   {
    switch(postion)
   { case -1:point=parent->left;break;

  case 1 :point=parent->right;break;

  case  0 :point=parent;break;
   }

 if(point->left==NULL&&point->right==NULL)
 {
  switch(postion)
  {
         case -1:parent->left=NULL;break;
         case 1:parent->right=NULL;break;
         case 0:parent=NULL;break;
  }

    free(point);
   return root;
    }

 if(point->left==NULL&&point->right!=NULL)
  {
   if(postion==-1)
    parent->left=point->right;
   else
    if(postion==1)
    parent->right=point->right;
    else
     root=root->right;

   free(point);
   return root;
  }
  
 if(point->left!=NULL&&point->right==NULL)
 {
  if(postion==-1)
   parent->left=point->left;
  else
   if(postion==1)
    parent->right=point->left;
   else
    root=root->left;
  return root;
 }

 if(point->left!=NULL&& point->right!=NULL)
 {
  parent=point;
  child=point->left;
  while(child->right!=NULL)
  {
   parent=child;
   child=child->right;
  }
  point->data=child->data;
  if(parent->left=child)
   parent->left=child->left;
  else
   parent->right=child->left;

  free(child);
  return root;
    }
  }

}

/*********中序遍历二叉树*************/
void Inorder(btree point)
{
 if(point!=NULL)
 {
  Inorder(point->left);
  printf("[%2d]",point->data);
  Inorder(point->right);
 }
}

/*********主程序测试函数***********/
void main()
{
 btree root=NULL;
 int deletetree;

 int nodelist[16]={0,5,4,6,2,0,0,8,1,3,0,0,0,0,7,9};

 root=create_btree(nodelist,1);

 printf("/n the original tree is");
 Inorder(root);
 printf("/n");

 printf("Input the value of the number /n");
 int test;
 scanf("%d",&test);

 root=deletenode(root,test);
 printf("/n the deleted tree is /n");
 Inorder(root);
 printf("/n");

 
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值