//1.根据给定的一组关键字(假设为int)序列,创建二叉排序树(CreateBst());
//2.分别使用递归和非递归方法,实现二叉排序树的查找操作(SreachK());
//3.计算查找成功与失败分别的ASL(ASLBST_V(),ASLBST_L())
//4.对二叉排序树进行插入关键字的操作(InsertBst());
//5.对二叉排序树进行删除关键字的操作(delBst());//删除方法一,删除方法二
//6.删除最小值(DelteMin())
//7.删除最大值(DeletMax())
#include<iostream>
#include<stack>
using namespace std;
#define TRUE 1
#define FALSE 0
typedef int KeyType, Status;
//二叉排序树的存储结构
typedef struct BSTNode {
KeyType key;
struct BSTNode* lchild, * rchild;
}BSTNode, * BiTree;
//非递归查找
Status SearchK1(BiTree bt, KeyType K, BiTree& p, BiTree& f) {
//在根为bt的二叉排序树上查找键值等于K的记录
//查找成功,用指针p指向目标;f指向目标的双亲,f初值为NULL
p = bt;
while (p) {
if (K < p->key) { f = p; p = p->lchild; } //左子树上继续找
else if (K > p->key)
{
f = p; p = p->rchild;
} //右子树上继续找
else return TRUE; //查找成功
}//end while
return FALSE; //查找失败
}
int total_depth = 0;
int total_nodes = 0;
// 使用一个辅助函数进行递归遍历所有节点,并累积路径深度
void calculateDepth(BiTree node, int depth) {
if (node == NULL) return;
total_depth += depth; // 累加路径深度
total_nodes++; // 统计节点个数
calculateDepth(node->lchild, depth + 1); // 递归遍历左子树
calculateDepth(node->rchild, depth + 1); // 递归遍历右子树
}
double ASL_T(BiTree bt) {//n为结点数
if (bt == NULL) return 0.0;
calculateDepth(bt, 1); // 从根节点开始,初始深度为1
// 计算平均查找长度(ASL)
cout << total_depth << "/" << total_nodes<<"=";
return (double)total_depth / total_nodes;
}
int total_depth_2 = 0;
int total_nodes_2;
int depth(BSTNode* bt, BSTNode* p) {//求深度
if (bt == nullptr) {
return 0;
}
if (p->key == bt->key) return 1;
else if (p->key < bt->key) return depth(bt->lchild, p) + 1;
else return depth(bt->rchild, p) + 1;
}
int countEmptyNodes(BiTree bt,BSTNode* root) {//求结点数和路径之和
if (root == nullptr) {
return 0;
}
int emptyNodes = 0;
if ((root->lchild && !root->rchild) || (!root->lchild && root->rchild)) {
emptyNodes = 1; total_depth_2 += depth(bt, root);
}
else if (!root->lchild && !root->rchild) {
emptyNodes = 2; total_depth_2 += 2*depth(bt, root);
}
return emptyNodes + countEmptyNodes(bt,root->lchild) + countEmptyNodes(bt,root->rchild);
}
double ASL_F(BiTree bt) {//求失败的平均路径
if (bt == NULL) return 0.0;
BSTNode* root = bt;
total_nodes_2 = countEmptyNodes(bt, root);
cout << total_depth_2 << "/" << total_nodes_2 << "=";
return (double)total_depth_2 / total_nodes_2;
}
//递归查找
Status SearchK2(BiTree bt, KeyType K, BiTree& p, BiTree& f) {
if (bt == NULL) {
p = NULL;
return FALSE;
}
if (K == bt->key) {
p = bt;
return TRUE;
}
f = bt;
if (K < bt->key) return SearchK2(bt->lchild, K, p, f);
else return SearchK2(bt->rchild, K, p, f);
}
//插入用来检验递归查找的正确
void InsertBst(BiTree& bt, KeyType k) {
BSTNode* f = NULL;
BSTNode* p = NULL;
if (!SearchK1(bt, k, f, p)) { //未找到R.key
BSTNode* S = new BSTNode;
S->key = k;
S->lchild = S->rchild = NULL;
if (!p) bt = S; //二叉排序树中的第一个结点
else if (S->key < p->key) p->lchild = S;
else p->rchild = S;
cout << "插入成功!";
}//end if
else cout << "该结点已经存在!\n";
}
//生成
void CreateBst(BiTree& bt, int n, KeyType a[]) {
bt = NULL;
for (int i = 0; i < n; i++) {
BSTNode* f = NULL;
BSTNode* p = NULL;
if (!SearchK1(bt, a[i], f, p)) { //未找到R.key
BSTNode* S = new BSTNode;
S->key = a[i];
S->lchild = S->rchild = NULL;
if (!p) bt = S; //二叉排序树中的第一个结点
else if (S->key < p->key) p->lchild = S;
else p->rchild = S;
}
}//for
}//end CreateBST
//删除
//方法一
void delBst(BiTree& bt, KeyType K) {
BSTNode* f = NULL;
BSTNode* p,*q;
//SearchK1(bt, k, p, f);
//if (p == NULL) {
// cout << "无这个删除结点!";
// return;
//}
//if (p->lchild == NULL && p->rchild == NULL) {//度为0
// if (f->lchild == p) f->lchild = NULL;
// else f->rchild = NULL;
// free(p);
//}
//else if (p->lchild && p->rchild == NULL) {//度为1
// if (f->lchild == p) f->lchild = p->lchild;
// else f->rchild = p->lchild;
// free(p);
//}
//else if (p->rchild && p->lchild == NULL) {//度为1
// if (f->lchild == p) f->lchild = p->rchild;
// else f->rchild = p->rchild;
// free(p);
//}
if (!SearchK1(bt, K, p, f)) return;//被删结点不存在
q = p->lchild;
if (p->rchild && p->rchild) {//度为2(方法一)
BSTNode* s = p->lchild;
while (s->rchild) s = s->rchild; //找P的中序前驱S
s->rchild = p->rchild; //P的右孩子交给S
if (!f) bt = q;
else if (f->lchild == p) f->lchild = p->lchild; else f->rchild = p->lchild; //P的左孩子交给F
free(p);
}
else { //被删结点p的度为1,0
q = p->rchild ? p->rchild : p->lchild;//q指向p的孩子
if (!f) bt = q; //被删结点p是树根,重新指定树根
else if (p == f->lchild)f->lchild = q; else f->rchild = q;
delete p; //释放被删结点p
}//else
cout << "删除成功!";
}
//删除(方法二)
void DeleteBST(BiTree& bt, KeyType K) { //删除bt上键值等于K的结点
BSTNode* f = NULL;
BSTNode* p,* q;
if (!SearchK1(bt, K, p, f)) return;//被删结点不存在
if (p->lchild && p->rchild) { //被删结点p的度为2—-方法2
q = p;BSTNode* s = p->lchild;
while (s->rchild) { q = s; s = s->rchild; } //找p的中序前驱s,
p->key = s->key; //用s的值替换p的值
if (q != p) q->rchild = s->lchild; else q->lchild = s->lchild;
delete s; //释放s
}//if
else { //被删结点p的度为1,0
q = p->rchild ? p->rchild : p->lchild;//q指向p的孩子
if (!f) bt = q; //被删结点p是树根,重新指定树根
else if (p == f->lchild)f->lchild = q; else f->rchild = q;
delete p; //释放被删结点p
}//else
cout << "删除成功!";
}
//删除最小值(三种情况)
void DeleteMin(BiTree &bt) {
BSTNode* p = bt;
while (p->lchild) p = p->lchild;
DeleteBST(bt, p->key);
}
//删除最大值(三种情况)
void DeleteMax(BiTree& bt) {
BSTNode* p = bt;
while (p->rchild) p = p->rchild;
DeleteBST(bt, p->key);
}
//中序遍历来检验操作
void inOrderTraverse(BiTree bt) {
if (bt != NULL) {
inOrderTraverse(bt->lchild);
cout << bt->key << " ";
inOrderTraverse(bt->rchild);
}
}
stack <BiTree>S;
//中序遍历(非递归)调用栈库来实现
void inOrder(BiTree bt) {
if (!bt) return;
//InitStack(S);
BSTNode* p = bt;
while (p || !S.empty()) {//EmptyStack(S)
while (p) { //沿着左链一路向下
S.push(p);//左孩子进栈
p = p->lchild;
}
p = S.top();
S.pop();
cout << p->key << " "; //访问
p = p->rchild;
}
}
int main() {
BiTree bt=NULL; KeyType k; KeyType* a=NULL;
int n;
char ch1 = '1', ch2;
while (ch1 == '1') {
cout << "\n\n\n\n";
cout << "\n\n\t\t\t\t二 叉 树\n";
cout << "\n\t\t*********************************************";
cout << "\n\t\t* 1----建 二 叉 排 序 树 *";
cout << "\n\t\t* 2----插 入 *";
cout << "\n\t\t* 3----删 除 方 法 一 *";
cout << "\n\t\t* 4----删 除 方 法 二 *";
cout << "\n\t\t* 5----删 除 最 小 值 *";
cout << "\n\t\t* 6----删 除 最 大 值 *";
cout << "\n\t\t* 7----查找成功的ASL *";
cout << "\n\t\t* 8----查找失败的ASL *";
cout << "\n\t\t* 9----中 序 遍 历 *";
cout << "\n\t\t* 0----返 回 *";
cout << "\n\t\t*********************************************";
cout << "\n\t\t请选择菜单号:";
cin >> ch2;
cout << "\n";
switch (ch2)
{
case'1':
cout << "输入二叉排序树节点个数n: ";
cin >> n;
a = new KeyType[n];
cout << "输入数据,中间空格: ";
for (int i = 0; i < n; i++)
cin >> a[i];
CreateBst(bt, n, a);
break;
case '2':
cout << "请输入你要插入的数:";
cin >> k;
InsertBst(bt, k);
cout << endl;
break;
case '3':
cout << "请输入你要删除的数:";
cin >> k;
delBst(bt, k);
cout << endl;
break;
case'4':
cout << "请输入你要删除的数:";
cin >> k;
DeleteBST(bt, k);
cout << endl;
break;
case'5':
DeleteMin(bt);
break;
case'6':
DeleteMax(bt);
break;
case'7':
cout << "查找成功的ASL:";
cout << ASL_T(bt) << endl;
total_depth = 0;
total_nodes = 0;
break;
case'8':
cout << "查找失败的ASL:";
cout << ASL_F(bt) << endl;
total_depth_2 = 0;
total_nodes_2 = 0;
break;
case'9':
cout << "此时的中序遍历结果(递归):";
inOrderTraverse(bt);
cout << endl;
cout << "此时的中序遍历结果(非递归):";
inOrder(bt);
cout << endl;
break;
case'0':
ch1 = 0;
break;
default:
cout << "\n\t\t***请注意:输入有误!***";
}
}
}
二叉排序树的操作
于 2024-12-17 11:08:28 首次发布