数据结构(实验C语言版)
查找及其应用
一、实验目的
(1)掌握在数组上进行各种查找的方法和算法
(2)深刻理解各种方法的特点,并能灵活运用
(3)加深对查找的理解,逐步培养解决实际问题的编程能力
二、实验环境
硬件环境要求:
PC机(单机)
使用的软件名称、版本号以及模块:
VS2010或Visual C++ 6.0或Win-TC等。
三、实验内容
设计一个程序实现二叉排序树的基本运算,并在此基础上完成如下功能:
(1) 由{4,9,0,1,8,6,3,5,2,7}创建一颗二叉排序bt并以括号表示输出。
(2) 判断bt是否为一颗二叉排序树。
(3) 查找关键字为6的结点,并输出其查找路径。
(4) 分别删除bt中关键字为4和5的节点,并输出删除后的二叉排序树。
四、实验要求
1、用 VS2010 工具创建文件或程序,输入代码后,进行编译运行或在控制台 执行。
2、观看程序运行结果,并根据结果进行思考,对程序进行修改和总结。
源代码
#include <stdio.h>
#include <malloc.h>
#define MaxSize 100
typedef int KeyType; //定义关键字类型
typedef char InfoType;
typedef struct node //记录类型
{
KeyType key; //关键字项
InfoType data; //其他数据域
struct node *lchild, *rchild; //左右孩子指针
} BSTNode;
int path[MaxSize]; //全局变量,用于存放路径
void DispBST(BSTNode *b); //函数说明
int InsertBST(BSTNode *&p, KeyType k);
BSTNode *CreatBST(KeyType A[], int n);
void DispBST(BSTNode *bt);
int JudgeBST(BSTNode *bt);
int SearchBST(BSTNode *bt, KeyType k);
void Delete1(BSTNode *p, BSTNode *&r);
void Delete(BSTNode *&p);
int DeleteBST(BSTNode *&bt, KeyType k);
int InsertBST(BSTNode *&p, KeyType k) //在以*p为根节点的BST中插入一个关键字为k的节点
{
if (p == NULL) //原树为空, 新插入的记录为根节点
{
p = (BSTNode *)malloc(sizeof(BSTNode));
p->key = k; p->lchild = p->rchild = NULL;
return 1;
}
else if (k == p->key)
return 0;
else if (k<p->key)
return InsertBST(p->lchild, k); //插入到*p的左子树中
else
return InsertBST(p->rchild, k); //插入到*p的右子树中
}
BSTNode *CreatBST(KeyType A[], int n)
//由数组A中的关键字建立一棵二叉排序树
{
BSTNode *bt = NULL; //初始时bt为空树
int i = 0;
while (i<n)
if (InsertBST(bt, A[i]) == 1) //将A[i]插入二叉排序树T中
{
printf(" 第%d步,插入%d:", i + 1, A[i]);
DispBST(bt); printf("\n");
i++;
}
return bt; //返回建立的二叉排序树的根指针
}
void DispBST(BSTNode *bt)
//以括号表示法输出二叉排序树bt
{
if (bt != NULL)
{
printf("%d", bt->key);
if (bt->lchild != NULL || bt->rchild != NULL)
{
printf("(");
DispBST(bt->lchild);
if (bt->rchild != NULL) printf(",");
DispBST(bt->rchild);
printf(")");
}
}
}
KeyType predt = -32767; //predt为全局变量,保存当前节点中序前趋的值,初值为-∞
int JudgeBST(BSTNode *bt) //判断bt是否为BST
{
int b1, b2;
if (bt == NULL) //空二叉树是排序二叉树
return 1;
else
{
b1 = JudgeBST(bt->lchild); //返回对左子树的判断,不是返回0,否则返回1
if (b1 == 0 || predt >= bt->key) //当左子树不是二叉排序树,或中序前趋(全局变量)大于当前根结点时
return 0; //返回“不是二叉排序树”
predt = bt->key; //记录当前根为右子树的中序前趋
b2 = JudgeBST(bt->rchild); //对右子树进行判断
return b2;
}
}
int SearchBST(BSTNode *bt, KeyType k)
//以递归方式输出从根节点到查找到的节点的路径
{
if (bt == NULL)
return 0;
else if (k == bt->key)
{
printf("%3d", bt->key);
return 1;
}
else if (k<bt->key)
SearchBST(bt->lchild, k); //在左子树中递归查找
else
SearchBST(bt->rchild, k); //在右子树中递归查找
printf("%3d", bt->key);
}
void Delete1(BSTNode *p, BSTNode *&r)
//当被删*p节点有左右子树时的删除过程
{
BSTNode *q;
if (r->rchild != NULL)
Delete1(p, r->rchild); //递归找最右下节点
else //找到了最右下节点*r
{
p->key = r->key; //将*r的关键字值赋给*p
q = r;
r = r->lchild; //将*r的双亲节点的右孩子节点改为*r的左孩子节点
free(q); //释放原*r的空间
}
}
void Delete(BSTNode *&p)
//从二叉排序树中删除*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 Delete1(p, p->lchild); //*p节点既有左子树又有右子树的情况
}
int DeleteBST(BSTNode *&bt, KeyType k)
//在bt中删除关键字为k的节点
{
if (bt == NULL) return 0; //空树删除失败
else
{
if (k<bt->key)
return DeleteBST(bt->lchild, k); //递归在左子树中删除关键字为k的节点
else if (k>bt->key)
return DeleteBST(bt->rchild, k); //递归在右子树中删除关键字为k的节点
else //k=bt->key的情况
{
Delete(bt); //调用Delete(bt)函数删除*bt节点
return 1;
}
}
}
int main()
{
BSTNode *bt;
KeyType k = 6;
int a[] = { 4, 9, 0, 1, 8, 6, 3, 5, 2, 7 }, n = 10;
printf("创建一棵BST树:");
printf("\n");
bt = CreatBST(a, n);
printf("BST:"); DispBST(bt); printf("\n");
printf("bt%s\n", (JudgeBST(bt) ? "是一棵BST" : "不是一棵BST"));
printf(" 查找%d关键字(递归,逆序):", k); SearchBST(bt, k);
//SearchBST(bt, k, path, -1);
printf("\n删除操作:\n");
printf(" 原BST:"); DispBST(bt); printf("\n");
printf(" 删除节点4:");
DeleteBST(bt, 4);
DispBST(bt); printf("\n");
printf(" 删除节点5:");
DeleteBST(bt, 5);
DispBST(bt);
printf("\n");
}
来源:CSDN
作者:chj65
链接:https://blog.csdn.net/chj65/article/details/103936162