编程练习——二叉查找树(BinarySearchTree)

来源:互联网 发布:汽车行业大数据专家 编辑:程序博客网 时间:2024/05/15 04:25

 BinarySearchTree和BinaryTree其实可以使用相同的构造和析构函数,所以继承吧。懒得再写一遍

template<class T>
class BinarySearchTree:public BinaryTree<T>
{
public:
 BinarySearchTree(T& data):BinaryTree<T>(data)
 {
  
 }

 ~BinarySearchTree()
 {
  
 }
 void insertNode(TreeNode<T>* node)
 {
  insertNode(this->head,node);
 }

 

 void insertNode(T& data)
 {
  TreeNode<T>* newNode = new TreeNode<T>(data);
  insertNode(this->head,newNode);
 }

 void deleteNode(T& data)
 {
  deleteNode(NULL,this->head,data);
 }

 TreeNode<T>* searchNode(T& data)
 {
  return searchNode(this->head,data);
 }

private:
 TreeNode<T>* insertNode(TreeNode<T>* subTree,TreeNode<T>* node)
 {
  if(subTree == NULL)
  {

   subTree = node;
  }
  else
  {
   
   if(subTree->getData() > node->getData())
   {
    subTree->setLeft(insertNode(subTree->getLeft(),node));
    
   }
   else if(subTree->getData() < node->getData())
   {
    subTree->setRight(insertNode(subTree->getRight(),node));
   }
   else
   {
    throw "insert same key";
   }
  }
  return subTree;
 }


 TreeNode<T>* searchNode(TreeNode<T>* subTree,T& data)
 {
  if(subTree == NULL)
  {
   return NULL;
  }
  else
  {
   if(subTree->getData() > data)
   {
    searchNode(subTree->getLeft(),data);
   }
   else if(subTree->getData() < data)
   {
    searchNode(subTree->getRight(),data);
   }
   else
   {
    return subTree;
   }
  }

 }

 void deleteNode(TreeNode<T>* pSubTree,TreeNode<T>* subTree,T& data)
 {
  if(subTree == NULL)
  {
   return ;
  }
  else
  {
   if(subTree->getData() > data)
   {
    deleteNode(subTree,subTree->getLeft(),data);
   }
   else if(subTree->getData() < data)
   {
    deleteNode(subTree,subTree->getRight(),data);
   }
   else
   {
    TreeNode<T>* assignNode = NULL;
    if(subTree->getLeft() == NULL && subTree->getRight() == NULL)
    {
     // no left, no right
     
    }
    else if(subTree->getLeft() == NULL && subTree->getRight() != NULL)
    {
     // no left child, but has right child
     assignNode = subTree->getRight();
    }
    else if(subTree->getLeft() != NULL && subTree->getRight() == NULL)
    {
     // no right, has left child
     assignNode = subTree->getLeft();
    }
    else
    {  
     // Or has both right and left child
     TreeNode<T>* parent = NULL;
     assignNode = getMaxNode(subTree->getLeft(),&parent);
     if(parent!= NULL)
     {
      parent->setRight(NULL);
      assert(assignNode!=NULL);
      assignNode->setLeft(subTree->getLeft());
     }
     assignNode->setRight(subTree->getRight());
    }
    

    if(pSubTree != NULL)
    {
    
     if(pSubTree->getLeft() == subTree)
     {
      pSubTree->setLeft(assignNode);
     }
     else
     {
      pSubTree->setRight(assignNode);
     }
    }
    else
    {
     this->head = assignNode;
    }
    delete subTree;
   }
  }
 }


 TreeNode<T>* getMaxNode(TreeNode<T>* subTree,TreeNode<T>** pNode)
 {
  if(subTree == NULL)
  {
   return NULL;
  }
  if(subTree->getRight()!= NULL)
  {
   pNode = &subTree;
   return getMaxNode(subTree->getRight(),pNode);
  }
  else
  {
   
   return subTree;
  }
 
 }

};

关于二叉查找树,其实插入和查找是一个很简单是事情。只要学会递归遍历,就可以轻松的做到。对于删除操作,删除规则与被删除节点是否有左右孩子节点有关。

1.当无左右节点。直接删除

2.当有右节点无左节点。将此节点删除,并用右节点取代此节点。

3.当有左节点(不管有无右节点)。删除时,将此树中序遍历中该节点的前一个节点代替该节点,再将该节点删除。

所以第3点要做一个寻找该节点中序遍历的前一节点。其实就是该节点左子树中序遍历的最后一个节点,详见getMaxNode()函数。

 

原创粉丝点击