查找系列之二叉排序树

                                                                    二叉排序树的创建、查询、插入与删除 

一、简述二叉排序树的思想

      动态查找表中主要有二叉树结构和树结构两种,而二叉树结构分为二叉排序树和平衡二叉树,树结构分为B-树和B+树等。

       二叉排序树可以是一颗空树二叉排序树的性质:二叉排序树上的节点满足左子树<父节点<右子树

       也就是说二叉排序树必须有顺序,且满足左子树<父节点<右子树

二、构建二叉排序树

        创建二叉排序树通常我们用链式存储结构的节点作为存储单位:如

     

  typedef struct Node{ 
          TypeData data;
          struct Node *leftChild;
          struct Node *rightChild;
  }

      这里我们先讲创建:先初始化得到根节点再来创建二叉排序树,这里必须先申请空间并且赋值后得到了一个新的节点,这时我们需要做的就是如何满足条件(左子树<父节点<右子树)的插入。所以必须进行一些简单的判断,这里就不多说了,可以看代码。

      创建代码:

 if(root != NULL){
	        free(root);	
	   }
	   root = (BiTreeNode *)malloc(sizeof(BiTreeNode));//申请空间来创建二叉排序树
	   if(root != NULL){
	        cout<<"空间申请成功!"<<endl;
	   }
	   cout<<"请输入要创建的数据:"<<endl;
	   cin >> num;
	   root->data = num;
	   root->leftChild = NULL;
	   root->rightChild = NULL;
	   while(p1 != NULL){
		   if(p1->data > num&&p1->leftChild!=NULL){
			   p1 = p1->leftChild;
		   }else if(p1->data < num&&p1->rightChild!=NULL){
			   p1 = p1->rightChild;
		   }else if(p1->data == num){
		       cout<<"已存在!"<<endl; 
			   return;
		   }
		   if(p1->leftChild == NULL&&num <p1->data){
			     p1->leftChild= root;
				 cout<<"创建成功!"<<endl;
				 break;
		   }else if(p1->rightChild == NULL && num > p1->data){
			     p1->rightChild = root;
				 cout<<"创建成功!"<<endl;
				 break;
		   }else{
			   cout<<"创建失败!"<<endl;
			   continue;
		   }
	   }
//这里是完整的初始化到创建的代码:

/**
*二叉树的初始化获取根节点
*@param 无
*@return BiTreeNode 
*/
BiTreeNode* BiTreeInitiate(){
	   BiTreeNode *root = NULL;
	   char c = 0;
	   int num = 0;
	   cout<<"请输入第一个根节点你想输入的数据:";cin >>num;
	   if(root != NULL){
	        free(root);	
	   }
	   root = (BiTreeNode *)malloc(sizeof(BiTreeNode));//申请空间来创建二叉排序树
	   if(root != NULL){
	        cout<<"空间申请成功!"<<endl;
	   }
	   root->data = num;
	   root->leftChild = NULL;
	   root->rightChild = NULL;
	   return root;
}
/**
*二叉排序树的创建
*@param  BiTreeNode *root 表示创建的二叉排序的根节点地址
*@return 无
*/
void BiTreeCreate(BiTreeNode *pRoot){
	   TypeData num =0;//在此针对的是以整型数据为例
	   BiTreeNode *p1 = pRoot;
	   BiTreeNode * p = NULL;
	   BiTreeNode *root = NULL;
	   char c = 0;
	   if(root != NULL){
	        free(root);	
	   }
	   root = (BiTreeNode *)malloc(sizeof(BiTreeNode));//申请空间来创建二叉排序树
	   if(root != NULL){
	        cout<<"空间申请成功!"<<endl;
	   }
	   cout<<"请输入要创建的数据:"<<endl;
	   cin >> num;
	   root->data = num;
	   root->leftChild = NULL;
	   root->rightChild = NULL;
	   while(p1 != NULL){
		   if(p1->data > num&&p1->leftChild!=NULL){
			   p1 = p1->leftChild;
		   }else if(p1->data < num&&p1->rightChild!=NULL){
			   p1 = p1->rightChild;
		   }else if(p1->data == num){
		       cout<<"已存在!"<<endl; 
			   return;
		   }
		   if(p1->leftChild == NULL&&num <p1->data){
			     p1->leftChild= root;
				 cout<<"创建成功!"<<endl;
				 break;
		   }else if(p1->rightChild == NULL && num > p1->data){
			     p1->rightChild = root;
				 cout<<"创建成功!"<<endl;
				 break;
		   }else{
			   cout<<"创建失败!"<<endl;
			   continue;
		   }
	   }
	   //判断是否继续输入,利用递归的调用来实现对程序的创建
	   cout<<"是否继续进行创建:Y/N"<<endl;
	   cin >> c;
	   if(c == 'Y' || c == 'y' ){   
	         BiTreeCreate(pRoot);
	   }else if(c == 'N'|| c == 'n'){
		   cout<<"二叉排序树创建完毕!"<<endl; 
	   }else{
	         cout<<"请重新输入:"<<endl;
			 cin >> c;
	   }
}

三、插入

        二叉排序树的插入事实上与创建类似,只不过创建需要不断的插入而插入一次插入一个元素罢了,插入时我们必须判断其是否已经存在,这是就需要对所有的节点进行一次遍历,这时刻以不用遍历所有的,因为二叉排序树是有序的,所以只需要从最小的遍历到大于它的元素就好了,如果不存在就插入反之则返回插入失败。

代码:

/**
*二叉排序树的插入
*@param BiTreeNode *B 表示创建好了的二叉树表地址
*@param TypeData num 表示要插入的整型数据
*@return 无
*/
void BiTreeInsert(BiTreeNode *B,TypeData num){
        BiTreeNode *current = NULL,*parent = NULL,*p= NULL ;
		current = B ;//current 指向二叉排序树的头节点
		//此时需要知道要插入的数据是否已存在,若存在,那么我们呢就不需要再插入,反之插入
		while(current != NULL){
			if(current->data == num ){
			    cout<<"已存在,不需要再进行插入!"<<endl;
			    return ;
			}
			parent = current;//用来记录要插入的数据应该插入的父节点的位置,即记录自己将要插入的位置
			if(num < current->data&¤t!= NULL){
		          current = current->leftChild;  	
			}else if(num > current->data && current != NULL){
				  current = current->rightChild;	
			}
		}
		//此时已经知道不存在,那么就要申请空间进行插入操做,但要判断是否内存空间满足
	    p  = (BiTreeNode *)malloc(sizeof(BiTreeNode));
		if(p == NULL){
		     cout<<"内存空间不足!"<<endl;
			 return;
		}
		//生成新的节点
		p->data = num;
		//暂时将左右节点置为空
		p->leftChild = NULL;
		p->rightChild = NULL;
		//这里进行插入操作对其左右节点赋上新的地址
		if(parent == NULL ){
		     B = p;
			 cout<<"插入成功!"<<endl;
			 return ;
		}else if(num < parent->data){
			parent->leftChild = p;
			cout<<"插入成功!"<<endl;
			return ;
		}else if(num > parent->data){
			parent->rightChild = p;
			cout<<"插入成功!"<<endl;
			return ;
		}
}

四、查找

       查找是很简单的,只需采用树的遍历就行了,这里采用中序遍历左->根->右,但有两种方式分别是循环和递归,这里采用的是递归啦。

代码:

/**
*二叉排序树的查找
*@param BiTreeNode *B表示记录二叉排序树的根节点地址
*@param TypeData num表示要查询的数
*@return BiTreeNode*
*/
BiTreeNode* BiTreeSearch(BiTreeNode *B,TypeData num){
	    BiTreeNode *p = B;//获取根节点地址
	    if(p == NULL){
			cout<<"此二叉树为空!"<<endl;
		    return p;
	    }
		if(p->data == num){
			 cout<<"进入查找操作---------"<<endl;
		     cout<<"成功的查找到了!num ="<<num<<endl;
			 cout<<"查找操作完毕---------"<<endl;
			 return p;
		}else{
			 if(p->leftChild == NULL&&p->rightChild==NULL){
				    cout<<"进入查找操作---------"<<endl;
		            cout<<"查找失败!-----------"<<endl;
					return p;
	          }
		}
		if(p->leftChild != NULL){
		    BiTreeSearch(p->leftChild,num);
	    }
	    if(p->rightChild != NULL){
		    BiTreeSearch(p->rightChild,num);
	    }
		if(p->data > num &&p->rightChild == NULL||p->data < num &&p->leftChild == NULL){
			 return p;
		}
}

五、修改

         这是一个麻烦的操作,这里就没怎么做好,只是供完善。

代码:

/**
*二叉排序树的修改
*@param BiTreeNode *B表示记录根节点地址
*@param TypeData num表示要修改的数
*@param TypeData d 表示想要改成的数
*@return 无
*/
void BiTreeModefy(BiTreeNode *B,TypeData num,TypeData d){
	    BiTreeNode *p = NULL;
	    //先要查找到要修改的元素
	    p=  BiTreeSearch(B,num);       
		if(p != NULL){
		     p->data = d;
			 cout<<"修改成功!"<<endl;
		}else{
		     cout<<"修改失败!"<<endl;
		}
}

六、删除

          删除时最难的一部分,这里来讲一下删除:

          要做删除就要考虑到其可能的所有情况

           1)要删除的节点无孩子节点,这是只需直接删除就是了

           2)要删除的节点有左孩子节点,这里只需将左孩子节点的地址给其父节点就是了

           3)要删除的节点有右孩子节点,这里只需将右孩子节点给其父节点,然后之前的左孩子节点必须给新的节点

           4)要删除既有左孩子节点又有右孩子节点,那么我们得考虑得把那个节点 放到要删除的节点的位置,这里我们需要做一个判断,即将右边的最小的节点放到要删除的节点的位置,那么这里的重点就是找到这个节点了,我们可以观察发现最左边的叶子节点就是这个节点,更细节,可以看代码调试:

代码:

/**
*二叉排序树的删除
*这里要靠考虑几种情况,一、删除无孩子的节点;二、删除只有左孩子的节点;三、删除只有右孩子的节点;四、删除既有左孩子又有右孩子的节点
*@param BiTreeNode *B表示记录的根节点的地址
*@param TypeData num 表示的是要删除的数
*@return 无
*/
void BiTreeDestroy(BiTreeNode *B,TypeData num){
	    cout<<"删除操作----"<<endl;
	    BiTreeNode *p = NULL;
		BiTreeNode *parent = NULL;
		BiTreeNode *p1 = B;//获取根节点地址
		BiTreeNode *pLeft = NULL;
		if(B == NULL){
		   cout<<"不存在!无法进行删除!"<<endl;
		   return ;
		}
		if(p1 == NULL){
		            return ;
		}
		//这里要获取其父节点
		while(p1!= NULL){
			   if(num  ==p1->data){
				    cout<<"存在这样的元素!data="<<p1->data<<endl;
		            break;
	           }
			   parent = p1;
	           if(num < p1->data){
			        p1=p1->leftChild;
			   } 
			   if(num > p1->data){
			         p1 = p1->rightChild;
			   }
			   if(p1 == NULL && parent->data != num){
			          cout<<"不存在这样元素!请重新进行选择和删除!"<<endl;
					  return ;
			   }
		}
	    //先要查找到要删除的元素
	    p=  BiTreeSearch(B,num);//获取到了要删除的数的地址
		if(p == NULL){
		   cout<<"不存在!无法进行删除!"<<endl;
		   return ;
		}
		//这里需要判断其属于那种情况
		if(p1->leftChild == NULL&&p1->rightChild == NULL){//此时属于无孩子节点的情况
			cout<<"------------------------------------------------------无孩子节点"<<endl;
			    if(parent == NULL&&p1!=NULL){
			         free(p);
					 cout<<"删除成功!-----"<<endl;
					 cout<<"二叉排序树为空!不能再进行操作,是否重新创建!"<<endl;
			         return ;
			    }
			    if(num < parent->data){
				    parent->leftChild = NULL;
			    }else if(num > parent->data){
	       	 		parent->rightChild = NULL;
		     	}
				free(p1);
			    cout<<"删除成功!----"<<endl;
			    return ;
		}
		if(p1->leftChild != NULL && p1->rightChild == NULL){//此时属于有左孩子节点的情况
			cout<<"--------------------------------------------有左孩子节点"<<endl;
			   if(parent == NULL&&p1 != NULL){
			        //这里不考虑根节点有左右孩子的情况
			         free(p);
					 cout<<"删除成功!-----"<<endl;
					 cout<<"二叉排序树为空!不能再进行操作,是否重新创建!"<<endl;
			         return ;
			   } 
			   if(num < parent->data){
			    	parent->leftChild = p1->leftChild;
			   }else if(num > parent->data){
				    parent->rightChild = p1->leftChild;
			   } 
			   free(p1);
			   cout<<"删除成功!"<<endl;
			   return ;
		}


		
		if(p1->leftChild == NULL && p1->rightChild != NULL){//此时属于有右孩子的情况
			cout<<"----------------------------------------------------有右孩子节点"<<endl;
		        if(parent == NULL&&p1 != NULL){
                     free(p1);
					 cout<<"删除成功!-----"<<endl;
					 cout<<"二叉排序树为空!不能再进行操作,是否重新创建!"<<endl;
			         return ;
			    }else if(num < parent->data){
				     parent->leftChild = p1->rightChild;
			    }else if(num > parent->data){
				     parent->rightChild = p1->rightChild;
			    }  
				cout<<"删除成功!"<<endl;
				return ;
		}
		if(p1->leftChild != NULL&& p1->rightChild !=NULL ){//此时属于既有右孩子又有左孩子的情况
			    cout<<"----------------------------------------------------既有左孩子节点也有右孩子节点"<<endl;
			    if(parent == NULL&&p1 != NULL){
				     free(p1);
					 cout<<"删除成功!-----"<<endl;
					 cout<<"二叉排序树为空!不能再进行操作,是否重新创建!"<<endl;
			         return ;
				}
				if(num <parent->data){
					if(p1->rightChild->leftChild == NULL&& p1->rightChild->rightChild == NULL){//这里判断其右节点无孩子节点的情况
						   p1->rightChild->leftChild = p1->leftChild;
						   /*if(num < parent->data){
						          parent->leftChild = p1->rightChild;
						   }else{
							     parent->rightChild = p1->rightChild; 
						   }*/
						   parent->leftChild = p1->rightChild;
						   cout<<"删除成功!"<<endl;
						   return;
						   //cout<<"///"<<p1->leftChild->data<<"  "<<p1->rightChild->leftChild->data<<endl; 
					}else if(p1->rightChild->leftChild != NULL ||p1->rightChild->rightChild != NULL){//这里判断其右节点有左孩子节点或右孩子节点
						pLeft = p1->rightChild;
						//获取到了要插入的节点的地址
						while( pLeft!= NULL){
							  if(pLeft->leftChild== NULL ){
							        break;
							  }else{
							       pLeft =  pLeft->leftChild;
							  }
						} 
						//执行删除操作
						if(p1->rightChild == pLeft){
						      pLeft->leftChild = p1->leftChild;
						}else{
							  if(pLeft->rightChild != NULL){
							       p1->rightChild->leftChild = pLeft->rightChild ; 
						      }else{
							       p1->rightChild->leftChild = NULL;
						      }
							  pLeft->rightChild = p1->rightChild;
						      pLeft->leftChild = p1->leftChild;    
						}
						parent->leftChild = pLeft;
					}
					free(p1);
					cout<<"左边-----删除成功!"<<endl;
					return ;
				}else if(num > parent->data){
				       if(p1->rightChild->leftChild == NULL&& p1->rightChild->rightChild == NULL){//这里判断其右节点无孩子节点的情况
						   p1->rightChild->leftChild = p1->leftChild;
						   parent->rightChild = p1->rightChild; 
						   cout<<"删除成功!"<<endl;
						   return;
				       } else if(p1->rightChild->leftChild != NULL ||p1->rightChild->rightChild != NULL){//这里判断其右节点有左孩子节点或右孩子节点
						pLeft = p1->rightChild;
						//获取到了要插入的节点的地址
						while( pLeft!= NULL){
							  if(pLeft->leftChild== NULL ){
							        break;
							  }else{
							       pLeft =  pLeft->leftChild;
							  }
						} 
						//执行删除操作
						if(p1->rightChild == pLeft){
						      pLeft->leftChild = p1->leftChild;
						}else{
							  if(pLeft->rightChild != NULL){
							       p1->rightChild->leftChild = pLeft->rightChild ; 
						      }else{
							       p1->rightChild->leftChild = NULL;
						      }
							  pLeft->rightChild = p1->rightChild;
						      pLeft->leftChild = p1->leftChild;    
						}
						parent->rightChild = pLeft;
					}
					   free(p1);	
					   cout<<"右边---删除成功!"<<endl;
					   return ;
			}
		}
}

//这里贴上全部代码以供调试,这里只是实现了基本功能,并且提供了简单的界面操作便于进行完善!

/**
*动态查找表有二叉排序树、平衡二叉树、此为二叉树结构,B-树、B+树、此为树结构
*二叉排序树在左右子树不为空的情况下,左子树小于根小于右子树即左<根<右即没有重复,若已存在,则不在继续插入
*/


/**
*动态查找表,二叉排序树的插入,查找与删除
*@author 菜鸟
*@version 2014.7.8
*/
#include <iostream>
#include <malloc.h>
#include <windows.h>
typedef int TypeData;
using namespace std;
//定义二叉树的节点
typedef struct node{
      TypeData data;
	  struct node *leftChild;
	  struct node *rightChild;
}BiTreeNode;
/**
*二叉树的初始化获取根节点
*@param 无
*@return BiTreeNode 
*/
BiTreeNode* BiTreeInitiate(){
	   BiTreeNode *root = NULL;
	   char c = 0;
	   int num = 0;
	   cout<<"请输入第一个根节点你想输入的数据:";cin >>num;
	   if(root != NULL){
	        free(root);	
	   }
	   root = (BiTreeNode *)malloc(sizeof(BiTreeNode));//申请空间来创建二叉排序树
	   if(root != NULL){
	        cout<<"空间申请成功!"<<endl;
	   }
	   root->data = num;
	   root->leftChild = NULL;
	   root->rightChild = NULL;
	   return root;
}
/**
*二叉排序树的创建
*@param  BiTreeNode *root 表示创建的二叉排序的根节点地址
*@return 无
*/
void BiTreeCreate(BiTreeNode *pRoot){
	   TypeData num =0;//在此针对的是以整型数据为例
	   BiTreeNode *p1 = pRoot;
	   BiTreeNode * p = NULL;
	   BiTreeNode *root = NULL;
	   char c = 0;
	   if(root != NULL){
	        free(root);	
	   }
	   root = (BiTreeNode *)malloc(sizeof(BiTreeNode));//申请空间来创建二叉排序树
	   if(root != NULL){
	        cout<<"空间申请成功!"<<endl;
	   }
	   cout<<"请输入要创建的数据:"<<endl;
	   cin >> num;
	   root->data = num;
	   root->leftChild = NULL;
	   root->rightChild = NULL;
	   while(p1 != NULL){
		   if(p1->data > num&&p1->leftChild!=NULL){
			   p1 = p1->leftChild;
		   }else if(p1->data < num&&p1->rightChild!=NULL){
			   p1 = p1->rightChild;
		   }else if(p1->data == num){
		       cout<<"已存在!"<<endl; 
			   return;
		   }
		   if(p1->leftChild == NULL&&num <p1->data){
			     p1->leftChild= root;
				 cout<<"创建成功!"<<endl;
				 break;
		   }else if(p1->rightChild == NULL && num > p1->data){
			     p1->rightChild = root;
				 cout<<"创建成功!"<<endl;
				 break;
		   }else{
			   cout<<"创建失败!"<<endl;
			   continue;
		   }
	   }
	   //判断是否继续输入,利用递归的调用来实现对程序的创建
	   cout<<"是否继续进行创建:Y/N"<<endl;
	   cin >> c;
	   if(c == 'Y' || c == 'y' ){   
	         BiTreeCreate(pRoot);
	   }else if(c == 'N'|| c == 'n'){
		   cout<<"二叉排序树创建完毕!"<<endl; 
	   }else{
	         cout<<"请重新输入:"<<endl;
			 cin >> c;
	   }
}
/**
*二叉排序树的插入
*@param BiTreeNode *B 表示创建好了的二叉树表地址
*@param TypeData num 表示要插入的整型数据
*@return 无
*/
void BiTreeInsert(BiTreeNode *B,TypeData num){
        BiTreeNode *current = NULL,*parent = NULL,*p= NULL ;
		current = B ;//current 指向二叉排序树的头节点
		//此时需要知道要插入的数据是否已存在,若存在,那么我们呢就不需要再插入,反之插入
		while(current != NULL){
			if(current->data == num ){
			    cout<<"已存在,不需要再进行插入!"<<endl;
			    return ;
			}
			parent = current;//用来记录要插入的数据应该插入的父节点的位置,即记录自己将要插入的位置
			if(num < current->data&¤t!= NULL){
		          current = current->leftChild;  	
			}else if(num > current->data && current != NULL){
				  current = current->rightChild;	
			}
		}
		//此时已经知道不存在,那么就要申请空间进行插入操做,但要判断是否内存空间满足
	    p  = (BiTreeNode *)malloc(sizeof(BiTreeNode));
		if(p == NULL){
		     cout<<"内存空间不足!"<<endl;
			 return;
		}
		//生成新的节点
		p->data = num;
		//暂时将左右节点置为空
		p->leftChild = NULL;
		p->rightChild = NULL;
		//这里进行插入操作对其左右节点赋上新的地址
		if(parent == NULL ){
		     B = p;
			 cout<<"插入成功!"<<endl;
			 return ;
		}else if(num < parent->data){
			parent->leftChild = p;
			cout<<"插入成功!"<<endl;
			return ;
		}else if(num > parent->data){
			parent->rightChild = p;
			cout<<"插入成功!"<<endl;
			return ;
		}
}


/**
*二叉排序树的查找
*@param BiTreeNode *B表示记录二叉排序树的根节点地址
*@param TypeData num表示要查询的数
*@return BiTreeNode*
*/
BiTreeNode* BiTreeSearch(BiTreeNode *B,TypeData num){
	    BiTreeNode *p = B;//获取根节点地址
	    if(p == NULL){
			cout<<"此二叉树为空!"<<endl;
		    return p;
	    }
		if(p->data == num){
			 cout<<"进入查找操作---------"<<endl;
		     cout<<"成功的查找到了!num ="<<num<<endl;
			 cout<<"查找操作完毕---------"<<endl;
			 return p;
		}else{
			 if(p->leftChild == NULL&&p->rightChild==NULL){
				    cout<<"进入查找操作---------"<<endl;
		            cout<<"查找失败!-----------"<<endl;
					return p;
	          }
		}
		if(p->leftChild != NULL){
		    BiTreeSearch(p->leftChild,num);
	    }
	    if(p->rightChild != NULL){
		    BiTreeSearch(p->rightChild,num);
	    }
		if(p->data > num &&p->rightChild == NULL||p->data < num &&p->leftChild == NULL){
			 return p;
		}
}
/**
*二叉排序树的修改
*@param BiTreeNode *B表示记录根节点地址
*@param TypeData num表示要修改的数
*@param TypeData d 表示想要改成的数
*@return 无
*/
void BiTreeModefy(BiTreeNode *B,TypeData num,TypeData d){
	    BiTreeNode *p = NULL;
	    //先要查找到要修改的元素
	    p=  BiTreeSearch(B,num);       
		if(p != NULL){
		     p->data = d;
			 cout<<"修改成功!"<<endl;
		}else{
		     cout<<"修改失败!"<<endl;
		}
}
/**
*二叉排序树的删除
*这里要靠考虑几种情况,一、删除无孩子的节点;二、删除只有左孩子的节点;三、删除只有右孩子的节点;四、删除既有左孩子又有右孩子的节点
*@param BiTreeNode *B表示记录的根节点的地址
*@param TypeData num 表示的是要删除的数
*@return 无
*/
void BiTreeDestroy(BiTreeNode *B,TypeData num){
	    cout<<"删除操作----"<<endl;
	    BiTreeNode *p = NULL;
		BiTreeNode *parent = NULL;
		BiTreeNode *p1 = B;//获取根节点地址
		BiTreeNode *pLeft = NULL;
		if(B == NULL){
		   cout<<"不存在!无法进行删除!"<<endl;
		   return ;
		}
		if(p1 == NULL){
		            return ;
		}
		//这里要获取其父节点
		while(p1!= NULL){
			   if(num  ==p1->data){
				    cout<<"存在这样的元素!data="<<p1->data<<endl;
		            break;
	           }
			   parent = p1;
	           if(num < p1->data){
			        p1=p1->leftChild;
			   } 
			   if(num > p1->data){
			         p1 = p1->rightChild;
			   }
			   if(p1 == NULL && parent->data != num){
			          cout<<"不存在这样元素!请重新进行选择和删除!"<<endl;
					  return ;
			   }
		}
	    //先要查找到要删除的元素
	    p=  BiTreeSearch(B,num);//获取到了要删除的数的地址
		if(p == NULL){
		   cout<<"不存在!无法进行删除!"<<endl;
		   return ;
		}
		//这里需要判断其属于那种情况
		if(p1->leftChild == NULL&&p1->rightChild == NULL){//此时属于无孩子节点的情况
			cout<<"------------------------------------------------------无孩子节点"<<endl;
			    if(parent == NULL&&p1!=NULL){
			         free(p);
					 cout<<"删除成功!-----"<<endl;
					 cout<<"二叉排序树为空!不能再进行操作,是否重新创建!"<<endl;
			         return ;
			    }
			    if(num < parent->data){
				    parent->leftChild = NULL;
			    }else if(num > parent->data){
	       	 		parent->rightChild = NULL;
		     	}
				free(p1);
			    cout<<"删除成功!----"<<endl;
			    return ;
		}
		if(p1->leftChild != NULL && p1->rightChild == NULL){//此时属于有左孩子节点的情况
			cout<<"--------------------------------------------有左孩子节点"<<endl;
			   if(parent == NULL&&p1 != NULL){
			        //这里不考虑根节点有左右孩子的情况
			         free(p);
					 cout<<"删除成功!-----"<<endl;
					 cout<<"二叉排序树为空!不能再进行操作,是否重新创建!"<<endl;
			         return ;
			   } 
			   if(num < parent->data){
			    	parent->leftChild = p1->leftChild;
			   }else if(num > parent->data){
				    parent->rightChild = p1->leftChild;
			   } 
			   free(p1);
			   cout<<"删除成功!"<<endl;
			   return ;
		}


		
		if(p1->leftChild == NULL && p1->rightChild != NULL){//此时属于有右孩子的情况
			cout<<"----------------------------------------------------有右孩子节点"<<endl;
		        if(parent == NULL&&p1 != NULL){
                     free(p1);
					 cout<<"删除成功!-----"<<endl;
					 cout<<"二叉排序树为空!不能再进行操作,是否重新创建!"<<endl;
			         return ;
			    }else if(num < parent->data){
				     parent->leftChild = p1->rightChild;
			    }else if(num > parent->data){
				     parent->rightChild = p1->rightChild;
			    }  
				cout<<"删除成功!"<<endl;
				return ;
		}
		if(p1->leftChild != NULL&& p1->rightChild !=NULL ){//此时属于既有右孩子又有左孩子的情况
			    cout<<"----------------------------------------------------既有左孩子节点也有右孩子节点"<<endl;
			    if(parent == NULL&&p1 != NULL){
				     free(p1);
					 cout<<"删除成功!-----"<<endl;
					 cout<<"二叉排序树为空!不能再进行操作,是否重新创建!"<<endl;
			         return ;
				}
				if(num <parent->data){
					if(p1->rightChild->leftChild == NULL&& p1->rightChild->rightChild == NULL){//这里判断其右节点无孩子节点的情况
						   p1->rightChild->leftChild = p1->leftChild;
						   /*if(num < parent->data){
						          parent->leftChild = p1->rightChild;
						   }else{
							     parent->rightChild = p1->rightChild; 
						   }*/
						   parent->leftChild = p1->rightChild;
						   cout<<"删除成功!"<<endl;
						   return;
						   //cout<<"///"<<p1->leftChild->data<<"  "<<p1->rightChild->leftChild->data<<endl; 
					}else if(p1->rightChild->leftChild != NULL ||p1->rightChild->rightChild != NULL){//这里判断其右节点有左孩子节点或右孩子节点
						pLeft = p1->rightChild;
						//获取到了要插入的节点的地址
						while( pLeft!= NULL){
							  if(pLeft->leftChild== NULL ){
							        break;
							  }else{
							       pLeft =  pLeft->leftChild;
							  }
						} 
						//执行删除操作
						if(p1->rightChild == pLeft){
						      pLeft->leftChild = p1->leftChild;
						}else{
							  if(pLeft->rightChild != NULL){
							       p1->rightChild->leftChild = pLeft->rightChild ; 
						      }else{
							       p1->rightChild->leftChild = NULL;
						      }
							  pLeft->rightChild = p1->rightChild;
						      pLeft->leftChild = p1->leftChild;    
						}
						parent->leftChild = pLeft;
					}
					free(p1);
					cout<<"左边-----删除成功!"<<endl;
					return ;
				}else if(num > parent->data){
				       if(p1->rightChild->leftChild == NULL&& p1->rightChild->rightChild == NULL){//这里判断其右节点无孩子节点的情况
						   p1->rightChild->leftChild = p1->leftChild;
						   parent->rightChild = p1->rightChild; 
						   cout<<"删除成功!"<<endl;
						   return;
				       } else if(p1->rightChild->leftChild != NULL ||p1->rightChild->rightChild != NULL){//这里判断其右节点有左孩子节点或右孩子节点
						pLeft = p1->rightChild;
						//获取到了要插入的节点的地址
						while( pLeft!= NULL){
							  if(pLeft->leftChild== NULL ){
							        break;
							  }else{
							       pLeft =  pLeft->leftChild;
							  }
						} 
						//执行删除操作
						if(p1->rightChild == pLeft){
						      pLeft->leftChild = p1->leftChild;
						}else{
							  if(pLeft->rightChild != NULL){
							       p1->rightChild->leftChild = pLeft->rightChild ; 
						      }else{
							       p1->rightChild->leftChild = NULL;
						      }
							  pLeft->rightChild = p1->rightChild;
						      pLeft->leftChild = p1->leftChild;    
						}
						parent->rightChild = pLeft;
					}
					   free(p1);	
					   cout<<"右边---删除成功!"<<endl;
					   return ;
			}
		}
}
/**
*二叉树的数据的输出
*@param BiTreeNode *B 
*@return 无
*/
void BiTreeOutPut(BiTreeNode *B){
	/*cout<<"B->data="<<B->data<<endl;
	cout<<"B->rightChild->data="<<B->rightChild->data<<endl;
	cout<<"B->rightChild->leftChild->data="<<B->rightChild->leftChild->data<<endl;
	cout<<"B->rightChild->rightChild->data="<<B->rightChild->rightChild->data<<endl;
	cout<<"B->rightChild->rightChild->leftChild->data="<<B->rightChild->rightChild->leftChild->data<<endl;*/
	 //输出各个节点的信息,采取中序遍历的方法即左->根->右
	if(B == NULL){
	        return ;
	}
	if(B->leftChild != NULL){
		    BiTreeOutPut(B->leftChild);
	}
	cout<<"数据元素:"<<B->data<<endl;
	if(B->rightChild != NULL){
		    BiTreeOutPut(B->rightChild);
	}
	if(B == NULL){
	       cout<<"输出完毕!"<<endl;
		   return ;
	}
}
/**
*菜单
*/
void menu(){
       cout<<"            |-----------------------------------------------|"<<endl;	
	   cout<<"            |-------------        菜单           -----------|"<<endl;
	   cout<<"            |-------------0、初始化二叉排序树    -----------|"<<endl;
	   cout<<"            |-------------1、创建二叉排序树      -----------|"<<endl;	
	   cout<<"            |-------------2、插入元素            -----------|"<<endl;	
	   cout<<"            |-------------3、查询元素            -----------|"<<endl;	
	   cout<<"            |-------------4、修改元素            -----------|"<<endl;	
	   cout<<"            |-------------5、删除元素            -----------|"<<endl;	
	   cout<<"            |-------------6、输出元素            -----------|"<<endl;
	   cout<<"            |-----------------------------------------------|"<<endl;
}
int count = 0;
void Operation(BiTreeNode *root){
	   menu();
       int input = 0;
	   int num = 0;
	   int d = 0;//要修改的目标元素
	   cout<<"请选择需要的服务:0-6"<<endl;
	   cin >> input;
	   if(input > 6||input <0){
	         cout<<"请重新选择:"<<endl;
			 menu();
			 Operation(root);
	   }
	   switch(input){
	         case 0:root = BiTreeInitiate();Operation(root);break;
	         case 1:BiTreeCreate(root);Operation(root);break;
			 case 2:cout<<"请输入要插入的元素:";cin >> num;BiTreeInsert(root,num);Operation(root);break;
			 case 3:cout<<"请输入要查找的元素:";cin >> num;BiTreeSearch(root,num);Operation(root);break;
	         case 4:cout<<"请输入要修改的元素和目标元素:";cin >> num>>d;BiTreeModefy(root,num,d);Operation(root);break;
		     case 5:cout<<"请输入要删除的元素:";cin >> num;BiTreeDestroy(root,num);Operation(root);break;
			 case 6:if(root == NULL){cout<<"已被删除!"<<endl;root = BiTreeInitiate();return ;}BiTreeOutPut(root);Operation(root);break;
	   }


}




int main(){
	 BiTreeNode *p = NULL;
     p = BiTreeInitiate();//获取根节点地址
	 Operation(p);
     system("PAUSE");
	 return 0;
}
代码经验证过!





  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
做一门精致,全面详细的 java数据结构与算法!!!让天下没有难学的数据结构,让天下没有难学的算法,不吹不黑,我们的讲师及其敬业,可以看到课程视频,课件,代码的录制撰写,都是在深夜,如此用心,其心可鉴,他不掉头发,谁掉头发???总之你知道的,不知道的,我们都讲,并且持续更新,走过路过,不要错过,不敢说是史上最全的课程,怕违反广告法,总而言之,言而总之,这门课你值得拥有,好吃不贵,对于你知识的渴求,我们管够管饱话不多说,牛不多吹,我们要讲的本门课程内容:稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二、二与数组转换、二排序(BST)、AVL、线索二、赫夫曼、赫夫曼编码、多路查找(BB+和B*)、图、图的DFS算法和BFS、程序员常用10大算法、二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法马踏棋盘算法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值