二叉排序树或者是一棵空树;或者是具有下列性质的二叉树:
1、若左子树不空,则左子树上所有结点的值均小于它的根结点的值
2、若右子树不空,则右子树上所有结点的值均大于它的根结点的值
3、左、右子树也分别为二叉排序树
/**
* 实验题目:
* 实现二叉排序树的基本运算算法
* 实验目的:
* 领会二叉排序树的定义、创建、查找和删除过程及其算法设计
* 实验内容:
* 设计程序,包含二叉排序树的创建、查找和删除算法,在此基础上编写程序,完成如下功能:
* 1、由关键字序列(4, 9, 0, 1, 8, 6, 3, 5, 2, 7)创建一颗二叉排序树bt并以括号表示法输出
* 2、判断bt是否为一颗二叉排序树
* 3、采用递归和非递归两种方法查找关键字为6的结点,并输出其查找路径
* 4、分别删除bt中的关键字为4和5的结点,并输出删除后的二叉排序树
*
*/
#include <stdio.h>
#include <stdbool.h>
#include <malloc.h>
#define MAX_SIZE 100
typedef int key_type; // 定义关键字类型
typedef char info_type;
typedef struct node { // 记录类型
key_type key; // 关键字项
info_type data; // 其他数据域
struct node *lchild; // 左孩子指针
struct node *rchild; // 右孩子指针
}BSTNode;
/*----------------以括号表示法输出二叉排序树bt------------------*/
void disp_bst(BSTNode *bt); // 函数声明
bool insert_bst(BSTNode *&bt, key_type key) // 在以bt为根结点的BST中插入一个关键字为key的结点
{
if(bt == NULL) // 原树为空,新插入的记录为根结点
{
bt = (BSTNode *)malloc(sizeof(BSTNode));
bt->key = key;
bt->lchild = bt->rchild = NULL;
return true;
}
else if(key == bt->key)
return false;
else if(key < bt->key)
return insert_bst(bt->lchild, key); // 插入到bt结点的左子树中
else
return insert_bst(bt->rchild, key); // 插入到bt结点的右子树中
}
/*----------------由数组a中的关键字建立一颗二叉排序树------------------*/
BSTNode *create_bst(key_type a[], int n)
{
BSTNode *bt = NULL; // 初始时bt为空树
int i = 0;
while(i < n)
{
if(insert_bst(bt, a[i]) == 1) // 将a[i]插入二叉排序树bst中
{
printf(" 第%d步,插入%d:", i + 1, a[i]);
disp_bst(bt);
printf("\n");
i++;
}
}
return bt;
}
/*----------------以括号表示法输出二叉排序树bt------------------*/
void disp_bst(BSTNode *bt)
{
if(bt != NULL)
{
printf("%d", bt->key);
if(bt->lchild != NULL || bt->rchild != NULL)
{
printf("("); // 有孩子结点时才输出(
disp_bst(bt->lchild); // 递归处理左子树
if(bt->rchild != NULL)
printf(","); // 有右孩子结点时才输出,
disp_bst(bt->rchild); // 递归处理右子树
printf(")"); // 有孩子结点时才输出)
}
}
}
key_type predt = -32767; // predt为全局变量,保存当前结点中序前驱的值,初值为-∞
/*----------------判断bt是否为BST------------------*/
bool judge_bst(BSTNode *bt)
{
bool b1, b2;
if(bt == NULL)
return true;
else
{
b1 = judge_bst(bt->lchild);
if(b1 == false || predt >= bt->key)
return false;
b2 = judge_bst(bt->rchild);
return b2;
}
}
/*----------------销毁一颗BST------------------*/
void destroy_bst(BSTNode *bt)
{
if(bt != NULL)
{
destroy_bst(bt->lchild);
destroy_bst(bt->rchild);
free(bt);
}
}
/*----------------以非递归方式输出从根结点到查找到的结点的路径------------------*/
void search_bst1(BSTNode *bt, key_type key, key_type path[], int i)
{
int j;
if(bt == NULL)
return;
else if(key == bt->key) // 找到关键字为key的结点
{
path[i + 1] = bt->key; // 输出其路径
for(j = 0; j <= i + 1; j++)
{
printf("%3d", path[j]);
}
printf("\n");
}
else
{
path[i + 1] = bt->key;
if(key < bt->key)
search_bst1(bt->lchild, key, path, i + 1); // 在左子树中递归查找
else
search_bst1(bt->rchild, key, path, i + 1); // 在右子树中递归查找
}
}
/*----------------以递归方式输出从根结点到查找到的结点的路径------------------*/
int search_bst2(BSTNode *bt, key_type key)
{
if(bt == NULL)
return 0;
else if(key == bt->key) // 找到关键字为key的结点
{
printf("%3d", bt->key); // 输出关键字
return 1;
}
else if(key < bt->key)
{
search_bst2(bt->lchild, key); // 在左子树中递归查找
}
else
{
search_bst2(bt->rchild, key); // 在右子树中递归查找
}
printf("%3d", bt->key); // 输出关键字
}
/*----------------被删除的结点p有左、右子树,r指向其左孩子------------------*/
void delete_node1(BSTNode *p, BSTNode *&r) // 指针的引用
{
BSTNode *q;
if(r->rchild != NULL) // 递归找结点r的最右下结点
{
delete_node1(p, r->rchild);
}
else // 找到最右下结点r(它没有右子树)
{
p->key = r->key; // 将结点r的值存放到结点p中(结点值替代)
p->data = r->data;
q = r; // 删除结点r
r = r->lchild; // 即用结点r的左孩子替代它
free(q); // 释放结点r的空间
}
}
/*----------------从二叉排序树中删除p结点------------------*/
void delete_node(BSTNode *&p)
{
BSTNode *q;
if(p->rchild == NULL) // p结点没有右子树的情况
{
q = p;
p = p->lchild;
free(q);
}
else if(p->lchild == NULL) // p结点没有左子树的情况
{
q = p;
p = p->rchild;
free(q);
}
else
delete_node1(p, p->lchild); // p结点既有左子树又有右子树的情况
}
/*----------------在bt中删除关键字为key的结点------------------*/
bool delete_bst(BSTNode *&bt, key_type key)
{
if(bt == NULL) // 空树删除失败
return false;
else
{
if(key < bt->key)
return delete_bst(bt->lchild, key); // 递归在左子树中删除关键字为key的结点
else if(key > bt->key)
return delete_bst(bt->rchild, key); // 递归在右子树中删除关键字为key的结点
else // key = bt->key的情况
{
delete_node(bt); // 调用函数delete_node删除bt结点
return true;
}
}
}
int main(int argc, char *argv[])
{
BSTNode *bt;
int path[MAX_SIZE];
key_type key = 7;
int a[] = {4, 9, 0, 1, 8, 6, 3, 5, 2, 7};
int n = 10;
printf("(1)创建一颗BST树:");
printf("\n");
bt = create_bst(a, n);
printf("(2)BST:");
disp_bst(bt);
printf("\n");
printf("(3)bt%s\n", judge_bst(bt) ? "是一颗BST" : "不是一颗BST");
printf("(4)查找%d关键字(递归,顺序):", key);
search_bst1(bt, key, path, -1);
printf("(5)查找%d关键字(非递归,逆序):", key);
search_bst2(bt, key);
printf("\n(6)删除操作:\n");
printf(" 原BST:");
disp_bst(bt);
printf("\n");
printf(" 删除结点4:");
delete_bst(bt, 4);
disp_bst(bt);
printf("\n");
printf(" 删除结点6:");
delete_bst(bt, 6);
disp_bst(bt);
printf("\n");
printf("(7)销毁BST\n");
destroy_bst(bt);
return 0;
}