/**
* 实验题目:
* 由有序序列创建一颗高度最小的二叉排序树
* 实验目的:
* 掌握二叉排序树的构造过程及其算法设计
* 实验内容:
* 设计程序,对于给定的一个有序的关键字序列,创建一颗高度
* 最小的二叉排序树。
* 解决思路:
* 要创建一颗高度最小的二叉排序树,就必须让左右子树的结点
* 个数越接近越好。由于给定的是一个关键字有序序列a[start...end],
* 所以让其中间位置的关键字a[mid]作为根结点,左序列a[start...mid-1]
* 构造左子树,右序列a[mid+1...end]构造右子树。
*/
#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;
}
}
}
/*-------------------创建一颗二叉排序树--------------------*/
BSTNode *create_bst1(key_type a[], int start_pos, int end_pos)
{
BSTNode *bt;
int mid;
if(end_pos < start_pos)
return NULL; // 返回空树
mid = (start_pos + end_pos) / 2;
bt = (BSTNode *)malloc(sizeof(BSTNode));
bt->key = a[mid]; // a[mid]作为根结点
bt->lchild = create_bst1(a, start_pos, mid - 1);// 左序列a[start...mid-1]构造左子树
bt->rchild = create_bst1(a, mid + 1, end_pos); // 右序列a[mid+1...end]构造右子树
return bt;
}
int main(int argc, char *argv[])
{
BSTNode *bt;
int n = 9;
key_type a[] = {1,2,3,4,5,6,7,8,9};
bt = create_bst1(a, 0, n - 1);
printf("bst:");
disp_bst(bt);
printf("\n");
destroy_bst(bt);
return 0;
}
测试结果:
bst:5(2(1,3(,4)),7(6,8(,9)))