二叉排序树的定义:
(1)对于任何一个结点,如果左子树不空,其左子树的所有节点的关键字均小于它的根节点的关键字。
(2)对于任何一个结点,如果右子树不空,其右子树的所有节点的关键字均大于它的根节点的关键字。
(3)它的左子树、右子树都是二叉排序树。
二叉排序树的特性:
其中序遍历将得到的序列是从小到大的序列。
二叉排序树的查找:
只要关键字不相等,且当前节点不为空树就继续搜索。当小于当前节点关键字时,搜索左子树,当大于时,搜索右子树。(下面的代码没有对不存在该关键字的情况处理,所以此时输出的实际上是其插入后的双亲结点)
二叉排序树的插入:
原理和上述类似,区别在于其采用递归。当搜索到空节点时,说明找到了插入位置,此时要动态分配内存建立新节点并插入。注意要返回当前的根节点,否则之后的调用会错误(仍然是空树)。
下面代码记录了插入结点时的双亲结点和查找结点时的双亲结点。
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
struct Node{
int data;
Node* left;
Node* right;
};
Node* Search(Node* T,int &key,int &f){
while(T!=NULL&&key!=T->data)
{
if(key<T->data)
{
f = T->data;//将当前的结点关键字记录下来
T=T->left;//搜索左子树
}
else
{
f = T->data;//将当前的结点关键字记录下来
T=T->right;//搜索右子树
}
}
return T;//返回双亲节点
}
Node* Insert(Node* T,int newKey,int &f){
//根节点、新节点的关键字、引用f(记录加入结点的双亲结点,全局变量)
//引用f是为了在整个递归期间只有一个
if(T==NULL){
T=(Node*)malloc(sizeof(Node));//动态分配结点内存
T->data = newKey;
T->left = T->right = NULL;
}
else if(newKey<T->data){//小于关键字
f = T->data;//接下来以左孩子为根插入,记录当前双亲结点
T->left = Insert(T->left,newKey,f);
}
else{
f = T->data;//接下来以有孩子为根插入,记录当前双亲结点
T->right = Insert(T->right,newKey,f);
}
return T;//返回当前根结点
}
int main(void){
int n;
while(scanf("%d",&n)!=EOF){
Node* root=NULL;//根节点
int newKey;
for(int i=0;i<n;i++){
int f=-1;
scanf("%d",&newKey);
root = Insert(root,newKey,f);//必须返回根节点,不然出下次插入时根节点还是NULL
printf("%d\n",f);
}
int k;
scanf("%d",&k);//查找k次
int searchKey;
for(int i=0;i<k;i++){
int f=-1;
scanf("%d",&searchKey);
Search(root,searchKey,f);
printf("%d\n",f);
}
}
return 0;
}