二叉搜索树BST

来源:互联网 发布:怎么才能做网络主播 编辑:程序博客网 时间:2024/05/14 16:30

二叉搜索树

二叉排序树又称“二叉查找树”、“二叉搜索树”。

二叉排序树:或者是一棵空树,或者是具有下列性质的二叉树:

1. 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;

2. 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;

3. 它的左、右子树也分别为二叉排序树。

 

二叉排序树通常采用二叉链表作为存储结构。中序遍历二叉排序树可得到一个依据关键字的有序序列,一个无序序列可以通过构造一棵二叉排序树变成一个有序序列,构造树的过程即是对无序序列进行排序的过程。每次插入的新的结点都是二叉排序树上新的叶子结点,在进行插入操作时,不必移动其它结点,只需改动某个结点的指针,由空变为非空即可。搜索、插入、删除的时间复杂度等于树高,期望O(logn),最坏O(n)(数列有序,树退化成线性表,如右斜树)。


查找:

思路:①若二叉树为空,则找不到,②先与根比较,相等则找到,否则若小于根则在左子树上继续查找,否则在右子树上继续查找。

递归算法:

BstTree BstSearch ( BstTree bst, DataType x )

{

  if ( bst==NULL )

    return NULL;

  else if ( bst->data==x )

    return bt;

  else if ( x<bst->data )

    return BstSearch ( bst->lchild, x);

  else

    return BstSearch ( bst->rchild, x);

}

非递归算法:

BstTree BstSearch ( BstTree bst, DataType x)

{

  p =bst;

  while ( p ) {

    if ( p->data==x )

     return p;

    else if ( x<p->data )

     p = p->lchild;

    else

     p = p->rchild;

  }

  return NULL;  // not found

}


插入:

思路:先查找,若找不到则插入结点作为最后访问的叶子结点的孩子。

新插入的结点总是叶子。


建立:

经过一系列插入操作可以建立二叉排序树。

给定关键字序列,建立二叉排序树。方法:①开始二叉树为空,②对每一个关键字,先进行查找,如果已存在,则不作任何处理,否则插入。

一句话,“从空树开始,每次插入一个关键字”。


删除:要注意删除结点为根节点的情况

分三种情况:
1、叶子
直接删除即可。
2、左子树或右子树为空
将左子树或右子树接到双亲上。
3、左右子树都不为空
用左子树上最大的结点替换被删除的结点,然后删除左子树的最大结点。

#include <iostream>using namespace std;struct node{int data;node *lchild,*rchild;};//插入void Insert(node *&T,int data){if(T==NULL)//空树时{T=new node;T->data=data;T->lchild=NULL;T->rchild=NULL;}else{node *p=T,*f=NULL;while(p!=NULL)//查找要插入的位置{if(p->data==data)return;f=p;//记录父结点,用来最后指向新的叶子结点if(data<p->data)p=p->lchild;elsep=p->rchild;}p=new node ;//产生一个叶子结点p->data=data;p->lchild=NULL;p->rchild=NULL;if(data<f->data)//将新的叶子结点加入到原树中f->lchild=p;elsef->rchild=p;}}//建立BSTnode*  Create()//生成二叉排序树{node *T=NULL;int i;cin>>i;while(i!=-1){Insert(T,i);cin>>i;}return T;}//中序遍历void Print(node *T)//中序遍历{if(T!=NULL){Print(T->lchild);cout<<T->data<<' ';Print(T->rchild);}}//查找void Find(node *T,int data,node *&f,node *&p)//返回多个值,将返回参数按引用或指针方式使用,不能传值{if(T==NULL)return ;else{p=T;while(p){if(p->data==data){//cout<<"find data= "<<p->data<<endl;return ;}f=p;//如果查找的是根节点,则f为初始值NULL,否则为p的父结点if(data<p->data){p=p->lchild;}elsep=p->rchild;}}}//删除结点void Delete(node * &T,int data){node * f=NULL,*p=NULL;if(T==NULL)//空树return;Find(T,data,f,p);if(p==NULL)//没有找到return;if(p->lchild==NULL && p->rchild==NULL)//删除叶子结点{if(f)//非根结点{if(f->lchild==p){f->lchild=NULL;}else{f->rchild=NULL;}}elseT=NULL;delete p;}else if(p->lchild==NULL){if(f)//非根结点{if(f->lchild==p){f->lchild=p->rchild;}else{f->rchild=p->rchild;}}elseT=p->rchild;delete p;}else//删除的结点含有左右子树:从待删除结点的左子树中选择最大值,交换,删除左子树中的最大值结点{node *p1=NULL,*p2=NULL;p1=p->lchild;//指向待删除结点的左子树p2=p1;while(p1!=NULL && p1->rchild!=NULL)//找最大值,p1所指向的为最大值{p2=p1;p1=p1->rchild;}p->data=p1->data;//交换p2->rchild=NULL;//删除delete p1;}}void main(){node *T=Create();Print(T);cout<<endl;Insert(T,99);Print(T);cout<<endl;node *f=NULL,*p=NULL;Find(T,99,f,p);if(p!=NULL)cout<<p->data<<endl;int i;cout<<"输入要删除的数"<<endl;cin>>i;Delete(T,i);cout<<endl;Print(T);system("pause");}





#include <iostream>using namespace std;struct node {int data;node *left;node *right;};void Inseart(node *&T,int data){if(T==NULL){T=new node;T->data=data;T->left=NULL;T->right=NULL;}else{node *f=NULL,*p=T;while(p){f=p;if(data==p->data)return;else if(data<p->data)p=p->left;elsep=p->right;}p=new node ;p->data=data;p->left=NULL;p->right=NULL;if(data<f->data)f->left=p;elsef->right=p;}}void Create(node *&T){int data;cin>>data;while(data!=-1){Inseart(T,data);cin>>data;}}void Print(node *T){if(T){Print(T->left);cout<<T->data<<endl;Print(T->right);}}void Search(node *T,int data ,node * &f,node * &p){if(T==NULL)return;p=T;while(p){if(data==p->data){return;}f=p; if(data<p->data){p=p->left;}elsep=p->right;}if(p==NULL){cout<<"not find"<<endl;p=f=NULL;}}void Delete(node * &T,int data){node *f=NULL,*p=T;Search(T,data,f,p);if(p==NULL)return;if(p->left==NULL && p->right==NULL){if(f==p){T=NULL;delete p;}else{if(f->left==p)f->left=NULL;elsef->right=NULL;delete p;}}else if(p->left==NULL)//有右子树{if(f==p)//要删除的是根结点{T=p->right;delete p;}else{if(f->left==p)f->left=p->right;elsef->right=p->right;}}else if(p->right==NULL)//有左子树{if(f==p){T=p->left;delete p;}else{if(f->left==p)f->left=p->left;elsef->right=p->left;}}else//有左右子树{node *pmax=p->left,*pre=p;while(pmax!=NULL && pmax->right!=NULL){pre=pmax;pmax=pmax->right;}swap(pmax->data,p->data);delete pmax;if(p==pre)//左子树里没有右子树pre->left=NULL;elsepre->right=NULL;}}void main(){node* T=NULL;Create(T);Print(T);int data;cin>>data;Delete(T,data);cout<<"-------------------"<<endl;Print(T);system("pause");}



0 0