二叉查找樹(插入、查找、遍歷、刪除.........)

【二叉查找樹的性質】

 二叉查找樹是滿足以下條件的二叉樹:

  1. 左子樹上的所有節點值均小於根節點值
  2. 右子樹上的所有節點值均不小於根節點值
  3. 左右子樹也都是二叉查找樹
  4. 不存在兩個節點的值相等

【二叉查找樹的插入、刪除過程】

二叉查找樹的插入過程如下:
1. 若當前的二叉查找樹爲空,則插入的元素爲根節點
2. 若插入的元素值小於根節點值,則將元素插入到左子樹中;若插入的元素值不小於根節點值,則將元素插入到右子樹中。

二叉查找樹的刪除,分三種情況進行處理:
1. p爲葉子節點,直接刪除該節點,再修改其父節點的指針(注意分是根節點和不是根節點)
2. p爲單支節點(即只有左子樹或右子樹)。讓p的子樹與p的父親節點相連,刪除p即可;(注意分是根節點和不是根節點)
3. p的左子樹和右子樹均不空。找到p的前驅s,s一定沒有右子樹,所以可以刪除s,用s的值代替p的值,讓s的父親節點t成爲s的左子樹的父親節點。

【代碼實現】

//binarysearch.h代碼
#ifndef binarysearch_h
#define binarysearch_h
template<class T> class BST;
template<class T>
class BSTnode
{
    friend class BST<T>;
private:
  T data;
  BSTnode<T> *lchild;
  BSTnode<T> *rchild;
};
template<class T>
class BST
{
public:
    BST()
    {
     root=0;
    } 

    void Insert(T item); //插入操作

    void display();
    void display(BSTnode<T> *currentnode,int i);//輸出元素的位置

    BSTnode<T> *Search(T item);
    BSTnode<T> *Search(BSTnode<T> *currentnode,T item);//遞歸查找

    BSTnode<T> *Search2(T item);//迭代查找

    void Inorder();
    void Inorder(BSTnode<T> *currentnode);//中序遍歷

    void delete_BST(T x);//刪除操作
private:
    BSTnode<T> *root;
};

//-------實現元素的按序插入-----------
template<class T>
void BST<T>::Insert(T item)
{
  BSTnode<T> *p=root;
  BSTnode<T> *q=0;  //q爲p的父節點
  while(p)
  {
   q=p;
   if(item<p->data)
   {
     p=p->lchild;
   }
   else if(item>p->data)
   {
     p=p->rchild;
    }
   else
   {
      // cout<<"不能重複插入"<<item<<endl;
       return;
   }
  }
  //找到插入位置q
  p=new BSTnode<T>();
  p->lchild=p->rchild=0;
  p->data=item;
  if(!root)  //當爲空樹時
  {
   root=p;
  }
  else if(item<q->data)//作爲q的左孩子
  {
   q->lchild=p;
  }
  else
  {
   q->rchild=p;//作爲q的右孩子
  }
}

//--------輸出每個元素的位置---------
template<class T>
void BST<T>::display()
{
  if(root)
     display(root,1);
   else
     cout<<"這是一棵空樹!"<<endl;
} 
template<class T>
void BST<T>::display(BSTnode<T> *currentnode,int i)
{
    cout<<"position "<<i<<":"<<currentnode->data<<endl;
    if(currentnode->lchild)
      display(currentnode->lchild,2*i);
    if(currentnode->rchild)
      display(currentnode->rchild,2*i+1);
}

//------二叉查找樹的遞歸查找-----------
template<class T>
BSTnode<T>* BST<T>::Search(T item)
{
    return Search(root,item);
}
template<class T>
BSTnode<T>* BST<T>::Search(BSTnode<T> *currentnode,T item)
{
  if(!currentnode)
  {
   return 0;  //沒找到,返回空指針
  }
  if(currentnode->data==item) 
      return currentnode;
  else if(currentnode->data>item) 
      return Search(currentnode->lchild,item);
  else
      return Search(currentnode->rchild,item);

}

//------二叉查找樹的迭代查找-----------
template<class T>
BSTnode<T>* BST<T>::Search2(T item)
{
    BSTnode<T>*p=root;
    while(p)
    {
      if(p->data==item)
          return p;
      else if(p->data>item)
          p=p->lchild;
      else
         p=p->lchild;
    }
   return 0;
}


//--------遞歸實現中序遍歷---------
template<class T>
void BST<T>::Inorder()
{
  cout<<"中序遍歷爲:";
  Inorder(root);
  cout<<endl;
}
template<class T>
void BST<T>::Inorder(BSTnode<T> *currentnode)
{
  if(currentnode)
  {
   Inorder(currentnode->lchild);
   cout<<currentnode->data<<" ";
   Inorder(currentnode->rchild);
  }
}


//-------------刪除元素--------------
template<class T>
void BST<T>::delete_BST(T x) 
{
    BSTnode<T> * p,*q;
    p=root; 
    //尋找被刪元素 
    while(p)
    { 
        if(x==p->data)//找到被刪元素 
        {  
           break;    
        }    
        else if(x<p->data)//沿左子樹找 
        { 
            q = p;        //q記錄p的父節點
            p = p->lchild;    
        }
        else           //沿右子樹找 
        {  
            q = p;    //q記錄p的父節點
            p = p->rchild;    
        }
    }
    if(!p)    //沒找到 
    {   
        cout << "沒有找到" << x << endl;    
    }
    //p爲待刪除節點
    if(p->lchild == 0 && p->rchild == 0) //情況1:p爲葉子節點 
    {  
        if(p == root) //p爲根節點 
        { 
           root = 0;    
        }
        else if(q->lchild == p)//p爲左子樹
        {   
            q->lchild =0;
        }        
        else  //p爲右子樹
        {
            q->rchild =0;    
        }
       delete(p);  //釋放節點p 
    }
    else if(p->lchild ==0 || p->rchild == 0)  //情況2:p爲單支子樹
    {  
        if(p == root) //p爲根節點 
        {  
            if(p->lchild ==0)
            {
               root = p->rchild;    
            }    
            else
            {
                root = p->lchild;    
            }
        }    
        else
        {
            if(q->lchild == p && p->lchild) //p是q的左子樹且p有左子樹 
            { 
                q->lchild = p->lchild;    //將p的左子樹鏈接到q的左指針上 
            }    
            else if(q->lchild == p && p->rchild) //p是q的左子樹且p有右子樹
            {
                q->lchild = p->rchild;    //將p的右子樹鏈接到q的左指針上 
            }
            else if(q->rchild == p && p->lchild)//p是q的右子樹且p有左子樹
            {
                q->rchild = p->lchild;   //將p的左子樹鏈接到q的右指針上 
            }
            else                        //p是q的右子樹且p有右子樹
            {
                q->rchild = p->rchild;//將p的右子樹鏈接到q的右指針上 
            }
        }
        delete(p);
    }
    else                           //情況3:p的左右子樹均不爲空 
    { 
        BSTnode<T> *t,*s;
        t=p;
        s = p->lchild;  //從p的左子節點開始 
        while(s->rchild) //找到p的前驅s(s一定沒有右子樹),即p左子樹中值最大的節點 
        {  
            t = s;     //t記錄s的父節點
            s = s->rchild;    
        }
        p->data = s->data;   //把節點s的值賦給p 
        if(t == p)
        {
            t->lchild = s->lchild;    
        }    
        else   
        {
            t->rchild = s->lchild;    //將p的前驅s的父節點指向s的左子樹
        }
        delete(s); 
    }
}
#endif
//main.cpp
#include"binarysearch.h"
#include <iostream>
using namespace std;
int main()
{
  BST<int> B1;
  B1.Insert(5);
  B1.Insert(3);
  B1.Insert(11);
  B1.Insert(8);
  B1.Insert(3);
  B1.display(); 
  B1.Inorder();
 // BSTnode<int> *p=B1.Search(3);
  BSTnode<int> *p=B1.Search2(3);
  if(p)
    cout<<"找到3!"<<endl;
  cout<<"刪除5後:"<<endl;
  B1.delete_BST(5);
  B1.display(); 
  B1.Inorder();
  system("pause");
  return 0;
}

【程序結果】

這裏寫圖片描述

發佈了64 篇原創文章 · 獲贊 29 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章