赞
踩
二叉搜索树,也可以叫它二叉查找树或二叉排序树。它是一种特殊的二叉树,基本的操作与二叉树并无不同。但是二叉搜索树的特点就是左子树中结点的键值都小于根结点的键值,右子树的键值都大于根结点的键值,简单来说就是左小右大,而且每个结点的键值都不相同,这样在操作的时候就会方便很多。二叉搜索树的操作集比之前的二叉树增加了几个,这样二叉搜索树的操作集就是:创建一个二叉树,判断树空,遍历,查找某个元素,查找最值,插入,删除。
二叉搜索树的存储方式也是链表。先给出头文件和定义,以便之后的局部代码分析。数据类型以int为例,其余同理。空结点的值置为0,应用的时候看具体情况,要把空结点的值置为在树中不可能出现的值,不然可能会出现错误。
#include<iostream>
#include<queue>
#define EMPTYNODE 0//空结点的值为0
using namespace std;
struct node
{
int data;
struct node* left;
struct node* right;
};
typedef struct node* N;
与创建一个二叉树一样,采用层序法,就是逐层输入数据,生成二叉搜索树。一定要注意二叉搜索树序列数据输入的顺序,既有二叉搜索树左小右大的顺序,又有一层一层,从左到右的顺序。
N CreateBinTree()//创建一个二叉树 { N roof,t; int temp; cout<<"请输入搜索二叉树序列:"; cin>>temp; if(temp==EMPTYNODE) { cout<<"该树为空。"<<endl; return NULL; } roof=new node; roof->data=temp; roof->left=NULL; roof->right=NULL; queue<N> q; q.push(roof); while(!q.empty()) { t=q.front(); q.pop(); cin>>temp;//输入左孩子 if(temp!=EMPTYNODE) { t->left=new node; t->left->data=temp; t->left->left=NULL; t->left->right=NULL; q.push(t->left); } cin>>temp;//输入右孩子 if(temp!=EMPTYNODE) { t->right=new node; t->right->data=temp; t->right->left=NULL; t->right->right=NULL; q.push(t->right); } } return roof; }
遍历方法也和二叉树是一样的。
void StoryBrowse(N n)//层序遍历 { if(!n) return ; else { queue<N> q; q.push(n); while(!q.empty()) { N temp; temp=q.front(); q.pop(); cout<<temp->data<<" "; if(temp->left) q.push(temp->left); if(temp->right) q.push(temp->right); } } }
N FindX(N n,int x)//递归查找某个元素 { if(!n) { cout<<"该树不含"<<x<<"这个元素。"<<endl; return NULL; } else { if(n->data==x) return n; else if(x<n->data) return FindX(n->left,x); else return FindX(n->right,x); } }
N Findx(N n,int x)//非递归查找某个元素 { if(!n) { cout<<"该树不含"<<x<<"这个元素。"<<endl; return NULL; } else { while(n) { if(n->data==x) return n; else if(x<n->data) n=n->left; else n=n->right; } cout<<"该树不含"<<x<<"这个元素。"<<endl; return n;//返回为空 } }
因为二叉搜索树的有序性,所以最值结点一定是叶子结点。最小值结点就是从根结点开始一直向左,直至叶子结点,这个结点就是最小值结点。最大值结点同理,就是一路向右。查找最值可以用递归和迭代两种方法实现。
N FindMax(N n)//递归法查找最大值
{
if(!n)
{
cout<<"该树没有最大值。"<<endl;
return NULL;
}
else if(!n->right)//已经到达叶子结点
return n;
else//查找右子树
return FindMax(n->right);
}
N FindMin(N n)//迭代法查找最小值
{
if(!n)
{
cout<<"该树没有最小值。"<<endl;
return NULL;
}
while(n)
{
if(!n->left)//已经到达叶子结点
return n;
else
n=n->left;
}
}
插入要根据插入元素与当前结点数据的大小关系,如果插入元素<当前结点的数据,那么把这个元素插入到当前结点的左子树上;如果插入元素>当前结点的数据,那么把这个元素插入到当前结点的右子树上;如果插入元素=当前结点的数据,说明这个元素已经存在,不需要再插入了,因为二叉搜索树每个结点的键值都是不同的。
N Insert(N n,int x)//插入一个元素 { if(!n)//创建一个只有一个结点的二叉树 { n=new node; n->data=x; n->left=NULL; n->right=NULL; } else { if(x<n->data) n->left=Insert(n->left,x); else if(x>n->data) n->right=Insert(n->right,x); } return n; }
删除一个结点分为三种情况,第一个是这个结点没有子结点,也就是这个结点就是叶子结点,这种情况最简单了,直接删除就可以;第二个是这个结点只有一个子结点,这种也比较简单,就是让指向这个结点的指针指向这个结点的子结点就可以了;第三个也是最复杂的一种情况,就是这个结点有左右两个子结点,有两种方法,一个是以左子树的最大结点来代替当前结点,另一个是以右子树的最小结点来代替当前结点,这两种方法都是首先进行数据修改,然后再删除最值结点即可。在删除的时候会遇到前两种情况中的一种,也就是说最值结点只可能没有子结点或者只有一个子结点,倘若最值结点有两个子结点(以最大值为例),根据二叉搜索树的性质,最值结点的右孩子要比最值结点大,那么最值结点就不是最大的了,所以不可能出现这种情况。
N DeleteX(N n,int x)//删除某个元素(以左子树最大结点代替当前结点) { if(!n) { cout<<"树中没有该元素,无法进行删除操作。"<<endl; return NULL; } else { if(x<n->data) n->left=DeleteX(n->left,x); else if(x>n->data) n->right=DeleteX(n->right,x); else//要删除的是当前结点 { N temp; if(n->left&&n->right)//有左右两棵子树 { temp=FindMax(n->left); n->data=temp->data; n->left=DeleteX(n->left,n->data); } else //只有一个子结点或者没有子结点 { temp=n; if(!n->left)//没有左孩子或没有子结点 n=n->right; else n=n->right; delete temp; } } return n; } }
N DeleteX(N n,int x)//删除某个元素(以右子树最小结点代替当前结点) { if(!n) { cout<<"树中没有该元素,无法进行删除操作。"<<endl; return NULL; } else { if(x<n->data) n->left=DeleteX(n->left,x); else if(x>n->data) n->right=DeleteX(n->right,x); else//要删除的是当前结点 { N temp; if(n->left&&n->right)//有左右两棵子树 { temp=FindMin(n->right); n->data=temp->data; n->right=DeleteX(n->right,n->data); } else //只有一个子结点或者没有子结点 { temp=n; if(!n->left)//没有左孩子或没有子结点 n=n->right; else n=n->right; delete temp; } } return n; } }
这是自己写的用于测试函数的数据,仅供参考。
在输入的时候以换行分隔:8,3,12,1,5,0,15,0,0,4,7,0,0,0,0,0,0。一定要注意空结点。
函数定义可见之前介绍。
int main() { N tree; tree=CreateBinTree(); StoryBrowse(tree); N temp; //temp=FindX(tree,5); temp=Findx(tree,5); cout<<endl; cout<<temp->data<<endl; cout<<"-------------------------------"<<endl; temp=FindMax(tree); cout<<temp->data<<endl; cout<<"-------------------------------"<<endl; temp=FindMin(tree); cout<<temp->data<<endl; cout<<"-------------------------------"<<endl; tree=Insert(tree,2); StoryBrowse(tree); cout<<endl; tree=DeleteX(tree,3); StoryBrowse(tree); cout<<endl; return 0; }
参考文献:《数据结构(第2版)》
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。