二叉排序树
先贴代码
#include<iostream>
//二叉排序树
using namespace std;
struct Node{
int data;
Node *lchild,*rchild;
};
class BST{
private:
Node* root;
public:
BST(int *array,int length);
bool deleteBST(int key){return deleteBST(root,key); }
void preOrder(){preOrder(root);}
void inOrder(){inOrder(root);}
Node* searchBST(int key){ return searchBST(root,key);}
private:
void insertBST(Node* &bt,int key);
void preOrder(Node* bt);
void inOrder(Node* bt);
bool deleteBST(Node* &bt,int key);
void deleteNode(Node* &bt);
Node* searchBST(Node* bt,int key);
};
//构造
BST::BST(int *array,int length){
root=NULL;
for(int i=0;i<length;i++){
insertBST(root,array[i]);
cout<<array[i]<<endl;
}
}
//插入
void BST::insertBST(Node* &bt,int key){
if(bt==NULL){
bt=new Node;
bt->data=key;
bt->lchild=NULL;
bt->rchild=NULL;
}
else{
if(bt->data>key) insertBST(bt->lchild,key);
else insertBST(bt->rchild,key);
}
return;
}
void BST::preOrder(Node* bt){
if(bt==NULL) return;
else{
cout<<bt->data<<" ";
preOrder(bt->lchild);
preOrder(bt->rchild);
}
return;
}
void BST::inOrder(Node* bt){
if(bt==NULL) return;
else{
inOrder(bt->lchild);
cout<<bt->data<<" ";
inOrder(bt->rchild);
}
return;
}
//删除
bool BST::deleteBST(Node* &bt,int key){
if(bt==NULL) return false;
else{
if(bt->data==key) deleteNode(bt);
else if(key<bt->data) deleteBST(bt->lchild,key);
else deleteBST(bt->rchild,key);
return true;
}
}
void BST::deleteNode(Node* &bt){
Node *p,*pre;
if(bt->lchild==NULL&&bt->rchild==NULL){
bt=NULL;
}
else if(bt->lchild==NULL){
p=bt;
bt=bt->rchild;
delete p;
}
else if(bt->rchild==NULL){
p=bt;
bt=bt->lchild;
delete p;
}
else{
p=bt;
pre=bt->lchild;
while(pre->rchild){
p=pre;
pre=pre->rchild;
}
bt->data=pre->data;
if(p!=bt) p->rchild=pre->lchild;
else p->lchild=pre->lchild;
}
}
//查找
Node* BST::searchBST(Node* bt,int key){
if(bt==NULL) return NULL;
else{
if(bt->data==key) return bt;
else if(key<bt->data) return searchBST(bt->lchild,key);
else return searchBST(bt->rchild,key);
}
}
int main(){
int array[6]={8,1,3,9,11,4};
BST t(array,6);
t.inOrder();
cout<<endl;
Node* p=t.searchBST(3);
cout<<p->data<<endl;
t.deleteBST(9);
t.inOrder();
return 0;
}
概念
二叉排序树(也称二叉查找树):或者是一棵空的二叉树,或者是具有下列性质的二叉树:
⑴ 若它的左子树不空,则左子树上所有结点的值均小于根结点的值;
⑵ 若它的右子树不空,则右子树上所有结点的值均大于根结点的值;
⑶ 它的左右子树也都是二叉排序树。
这是内含递归思想的定义,应该比较好理解。
我这里贴一个图:
之前学过的二叉树不是有前序、中序、后序、层序遍历嘛。这里我们可以通过中序遍历得到这个二叉排序树拍好的序。
储存结构
本质上就是一个二叉树,只不过在构造的时候有了一些规定,所以储存结构就是一个结构体指针代表根节点
struct Node{
int data;
Node *lchild,*rchild;
};
Node* root;
代码实现
插入
为什么会把插入写在构造之前呢?
因为构造是多次的插入啊hhhhh
1.思路:从根节点出发,如果为空,直接插入;如果不为空,作比较,若当前key小于扫描节点,就往左边走,若当前key大扫描到的节点,就往右边走。
2.代码:
void insert(Node* bt,int key){
if(bt==NULL){
bt=new Node;
bt->data=key;
bt->lchild=NULL;
bt->rchild=NULL;
}
else{
if(key<bt->data) insert(bt->lchild,key);
else insert(bt->rchild,key);
}
return;
}
3.注意:
每一次新增结点时都需要new一下。
这里用的是封装的思想,写了一堆public和private,因为外界无法访问root。当然你也可以自己写一个getRoot()函数。 其他的函数也是同样的道理。
构造
1.思路: 传一个数组,然后依次插入。
2.代码:
BST::BST(int *array,int length){
root=NULL;
for(int i=0;i<lehgth;i++) insert(root,array[i]);
}
查找
也很简单。
跟插入类似。
直接代码
Node* BST::searchBST(Node* bt,int key){
if(bt==NULL) return NULL;
else{
if(bt->data==key) return bt;
else if(key<bt->data) return searchBST(bt->lchild,key);
else return searchBST(bt->rchild,key);
}
}
删除
为了防止我的文章过于水,决定在这里写一些删除的内容,这个有一些难度。
1.思路: 先找到要删除的结点位置,再删除结点(废话哒咩!)
这里重点讲一下删除结点的情况,根据待删除的结点拥有左右孩子的情况分为四个类型:
1°没有左右孩子(即为叶节点):直接delete该结点
2°只有一个左(右)孩子:讲该结点的孩子全部托付给双亲,然后delete
3°有两个孩子:
找到待删除结点K左孩子M的最右孩子N,将他覆盖K,这时候就需要处理遗留问题了:N如果有左孩子嘞?(肯定只可能有左孩子)
根据上面只有一个孩子的做法,托付给双亲O。并且有两种情况:
左孩子M有右孩子时 将N的左孩子给O的右边
左孩子M没有右孩子时 直接将左边就覆盖上去
(会不会没讲明白啊,我待会画一个图,不水吧)
else{
p=bt;
pre=bt->lchild;
while(pre->rchild){
p=pre;
pre=pre->rchild;
}
bt->data=pre->data;
if(p!=bt) p->rchild=pre->lchild;
else p->lchild=pre->lchild;
}
所以这里可以好好看看while()循环,嘻嘻。
明天就是高考了,祝大家手摘星辰!