【二叉查找樹的性質】
二叉查找樹是滿足以下條件的二叉樹:
- 左子樹上的所有節點值均小於根節點值
- 右子樹上的所有節點值均不小於根節點值
- 左右子樹也都是二叉查找樹
- 不存在兩個節點的值相等
【二叉查找樹的插入、刪除過程】
二叉查找樹的插入過程如下:
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;
}