赞
踩
(1)若左子树非空,则左子树上所有结点的值均小于根节点的值
(2)若右子树非空,则右子树上所有结点的值均大于根节点的值
(3)左右子树分别也是一棵二叉排序树
tip:可以是一棵空树
(1)因为二叉排序树的中序遍历是一个有序递增序列,可以对已经建立的二叉树进行中序遍历,如果满足则判断是
树结点的结构体:
struct tree{
int data;
struct tree* lchild;
struct tree* rchild;
};
- //递归创建结点
- void Creat(int a,tree* &T){
- if(T==NULL){
- T=new tree;
- T->data=a;
- T->lchild=NULL;
- T->rchild=NULL;
- }
- else if(a>T->data){
- Creat(a,T->rchild);
- }
- else{
- Creat(a,T->lchild);
- }
- }
-
- //传入数组,一次性插入
- void Insert(tree* &T,int A[],int len){
- for(int i=0;i<=len;i++){
- Creat(A[i],T);
- }
- }
- //查找指定结点(输出当前结点是否存在),如果没有就插入
- void find(tree* &T,int a){
- tree* K=T; //T指针指向二叉排序树的根节点,K为工作指针
- tree* pre; //pre指向当前工作指针的上一个结点,用于插入确定插入位置
- while(K!=NULL&&a!=K->data){
- if(a>K->data){
- pre=K;
- K=K->rchild;
- }else{
- pre=K;
- K=K->lchild;
- }
- }
- if(K==NULL){
- tree* P; //工作指针
- P=new tree;
- P->data=a;
- if(P->data>pre->data){
- pre->rchild=P;
- P->lchild=NULL;
- P->rchild=NULL;
- }
- else{
- pre->lchild=P;
- P->lchild=NULL;
- P->rchild=NULL;
- }
- cout<<"不存在,已插入 "<<a<<" 这个结点"<<endl;
- }else{
- cout<<"存在"<<endl;
- }
- }
- //删除某一结点,若不存在则提示
- //①当该结点是叶子结点时,直接删除
- //②当该结点有一个左孩子或者一个右孩子时,让其孩子结点代替他的位置
- //③当左右孩子都存在时找中序遍历的下一个(或上一个)结点代替其位置
- void delect(tree* &T,int a){
- //首先找到要删除的结点
- tree* Pre;
- tree* P=T; //定义工作指针
- while(P!=NULL&&a!=P->data){ //这两个判定条件不能颠倒
- if(a>P->data){
- Pre=P;
- P=P->rchild;
- }else{
- Pre=P;
- P=P->lchild;
- }
- }
- if(P==NULL){
- cout<<"要删除的结点不存在"<<endl;
- }else{
- // ①当该结点是叶子结点时,直接删除
- if(P->lchild==NULL&&P->rchild==NULL){
- if(P->data>Pre->data){
- Pre->rchild=NULL;
- }else{
- Pre->lchild=NULL;
- }
- cout<<"已删除 "<<a<<endl;
- }
- //②当该结点有一个左孩子或者一个右孩子时,让其孩子结点代替他的位置
- if((P->lchild!=NULL&&P->rchild==NULL)||(P->rchild!=NULL&&P->lchild==NULL)){
- if(P->data>Pre->data){
- if(P->lchild!=NULL){
- Pre->rchild=P->lchild;
- }else{
- Pre->rchild=P->rchild;
- }
- }
- if(P->data<Pre->data){
- if(P->lchild!=NULL){
- Pre->lchild=P->lchild;
- }else{
- Pre->lchild=P->rchild;
- }
- }
- cout<<"已删除 "<<a<<endl;
- }
- //③当左右孩子都存在时找中序遍历的下一个(或上一个结点)结点代替其位置 ,这里采用中序遍历上一个结点来代替
- if(P->lchild!=NULL&&P->rchild!=NULL){
- tree* Q=P->lchild; //工作指针
- tree* Pre2; //用于记录最终遍历到的结点的前序结点,用于后期连接
- while(Q->rchild){
- Pre2=Q;
- Q=Q->rchild;
- }
- P->data=Q->data;
- if(P!=Pre2){
- Pre2->rchild=Q->lchild;
- }else{
- Pre2->lchild=Q->lchild;
- }
- delete(Q);
- cout<<"已删除 "<<a<<endl;
- }
-
- }
-
- }
注意:这里采用的是找左子树的最右下结点来代替要删除的结点(对于王道书上的用中序遍历的下一个结点的方法是一样的,后面也会附上代码)
第一步:找到左子树的最右下结点(这里用到了一个工作指针Q)
无非只有下面几种情况:
- if(P->lchild!=NULL&&P->rchild!=NULL){
- tree* Q=P->rchild;
- tree* Pre2;
- while(Q->lchild){
- Pre2=Q;
- Q=Q->lchild;
- }
- P->data=Q->data;
- if(P!=Pre2){
- Pre2->lchild=Q->rchild;
- }else{
- Pre2->rchild=Q->rchild;
- }
- delete(Q);
- }
- #include<iostream>
- using namespace std;
-
- struct tree{
- int data;
- struct tree* lchild;
- struct tree* rchild;
- };
-
- //建立创建,传入一个完整的数组
- void Creat(int a,tree* &T){
- if(T==NULL){
- T=new tree;
- T->data=a;
- T->lchild=NULL;
- T->rchild=NULL;
- }
- else if(a>T->data){
- Creat(a,T->rchild);
- }
- else{
- Creat(a,T->lchild);
- }
- }
-
- //传入数组,一次性插入
- void Insert(tree* &T,int A[],int len){
- for(int i=0;i<=len;i++){
- Creat(A[i],T);
- }
- }
-
- //中序遍历
- void midorder(tree* T){
- if(T!=NULL){
- midorder(T->lchild);
- cout<<T->data<<" ";
- midorder(T->rchild);
- }
- }
-
- //判断是否是二叉排序树
- //对树进行中序遍历,然后判断是否有序递增
-
- //查找指定结点(输出当前结点是否存在),如果没有就插入
- void find(tree* &T,int a){
- tree* K=T; //T指针指向二叉排序树的根节点,K为工作指针
- tree* pre; //pre指向当前工作指针的上一个结点,用于插入确定插入位置
- while(K!=NULL&&a!=K->data){
- if(a>K->data){
- pre=K;
- K=K->rchild;
- }else{
- pre=K;
- K=K->lchild;
- }
- }
- if(K==NULL){
- tree* P; //工作指针
- P=new tree;
- P->data=a;
- if(P->data>pre->data){
- pre->rchild=P;
- P->lchild=NULL;
- P->rchild=NULL;
- }
- else{
- pre->lchild=P;
- P->lchild=NULL;
- P->rchild=NULL;
- }
- cout<<"不存在,已插入 "<<a<<" 这个结点"<<endl;
- }else{
- cout<<"存在"<<endl;
- }
- }
-
- //删除某一结点,若不存在则提示
- //①当该结点是叶子结点时,直接删除
- //②当该结点有一个左孩子或者一个右孩子时,让其孩子结点代替他的位置
- //③当左右孩子都存在时找中序遍历的下一个(或上一个)结点代替其位置
- void delect(tree* &T,int a){
- //首先找到要删除的结点
- tree* Pre;
- tree* P=T; //定义工作指针
- while(P!=NULL&&a!=P->data){ //这两个判定条件不能颠倒
- if(a>P->data){
- Pre=P;
- P=P->rchild;
- }else{
- Pre=P;
- P=P->lchild;
- }
- }
- if(P==NULL){
- cout<<"要删除的结点不存在"<<endl;
- }else{
- // ①当该结点是叶子结点时,直接删除
- if(P->lchild==NULL&&P->rchild==NULL){
- if(P->data>Pre->data){
- Pre->rchild=NULL;
- }else{
- Pre->lchild=NULL;
- }
- cout<<"已删除 "<<a<<endl;
- }
- //②当该结点有一个左孩子或者一个右孩子时,让其孩子结点代替他的位置
- if((P->lchild!=NULL&&P->rchild==NULL)||(P->rchild!=NULL&&P->lchild==NULL)){
- if(P->data>Pre->data){
- if(P->lchild!=NULL){
- Pre->rchild=P->lchild;
- }else{
- Pre->rchild=P->rchild;
- }
- }
- if(P->data<Pre->data){
- if(P->lchild!=NULL){
- Pre->lchild=P->lchild;
- }else{
- Pre->lchild=P->rchild;
- }
- }
- cout<<"已删除 "<<a<<endl;
- }
- //③当左右孩子都存在时找中序遍历的下一个(或上一个结点)结点代替其位置 ,这里采用中序遍历上一个结点来代替
- // if(P->lchild!=NULL&&P->rchild!=NULL){
- // tree* Q=P->lchild; //工作指针
- // tree* Pre2; //用于记录最终遍历到的结点的前序结点,用于后期连接
- // while(Q->rchild){
- // Pre2=Q;
- // Q=Q->rchild;
- // }
- // P->data=Q->data;
- // if(P!=Pre2){
- // Pre2->rchild=Q->lchild;
- // }else{
- // Pre2->lchild=Q->lchild;
- // }
- // delete(Q);
- // cout<<"已删除 "<<a<<endl;
- // }
- if(P->lchild!=NULL&&P->rchild!=NULL){
- tree* Q=P->rchild;
- tree* Pre2;
- while(Q->lchild){
- Pre2=Q;
- Q=Q->lchild;
- }
- P->data=Q->data;
- if(P!=Pre2){
- Pre2->lchild=Q->rchild;
- }else{
- Pre2->rchild=Q->rchild;
- }
- delete(Q);
- cout<<"已删除 "<<a<<endl;
- }
- }
-
- }
-
- int main(){
- tree* T=NULL;
- int A[]={23,89,65,12,17,3,9,90,21,63,71};
- Insert(T,A,10);
- midorder(T);
- delect(T,89);
- midorder(T);
- find(T,89);
- midorder(T);
- return 0;
- }
结语:感谢观看,有什么问题望指正
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。