6、二叉排序树的基本操作(**)
任务: 编写算法实现对依次输入的关键字序列建立二叉排序树,并能实现二叉排序树的查找、插入和删除运算。
一、算法设计
1.建立二叉树的过程实际上就是一个一个结点的插入过程,将读入的第一个结点看作是根结点,第二个来时,与第一个结点进行比较,小的话作为左孩子,大的话作为右孩子。以此类推,第三个,第四个都是如此。查找过程也与此类似,从根结点开始,与所给的关键字数值进行比较,比根结点的值大,跑向右孩子,比根结点的数值小,跑向左孩子。一直比较,直到数值匹配符合,说明查找成功。若是当前结点左右孩子都为空,则证明这个数值并没有存入二叉排序树当中。插入运算的话,对于给定的数值,需要先进行一遍查找遍历,若当前数值已经存在就直接退出功能。否则,记录下最后一个查找的结点,即为需要插入的位置(当前结点的左孩子或者是右孩子)。删除运算需要分情况讨论,若是叶子结点,直接删除没有什么好说的,其他的都不变。若当前结点有单个孩子,不管是右孩子还是左孩子,此结点被删除之后,直接由孩子来替代。如果此结点有两个孩子,这里有两种方法可以用来处理。假设被删结点有右孩子还有左孩子,那么被删除之后,可以在其左子树上遍历,找到左子树上最大的数值结点来代替该节点。或者是右子树寻找数值最小的结点来代替。数值最大、数值最小的结点必为叶子节点。这样,整个二叉树的基本运算就结束了。在此基础上,可以通过树的中序遍历对该树进行打印,打印出来的数值肯定也是按照由小到大的顺序排列的。
各个函数之间的调用关系如下图所示:
main() |
|||
mainjiemian() |
|||
InsertBST() PrintBST() |
SearchBST() PrintBST() |
DeleteBST() PrintBST() |
jieshu() |
mainjiemian() |
2.本程序中包含7个模块
(1)主函数:int main();
(2)主菜单函数:void mainjiemian();
(3)退出函数:void jieshu();
(4)中序遍历二叉树并进行打印:void PrintBST(BiTree T);
(5)删除结点:int DeleteBST(BiTree T, datatype value);
(6)插入节点:BiTNode * InsertBST(BiTNode *T, int kx);
(7)查找结点:int SearchBST(BiTNode *T, datatype kx);
3.元素类型、结点类型和指针类型
typedefstruct BiTNode
{
datatype key = -1;/*关键字*/
struct BiTNode *lchild = NULL, *rchild =NULL;/*左、右子树*/
}BiTNode,*BiTree;/*二叉排序树的结点与指向根节点的指针*/
二、实验测试
源代码:
#pragma warning(disable:4996) #include<stdio.h> #include<cstdio> #include<string> #include<string.h> #include<vector> #include<algorithm> #include<queue> #include<stack> #include<math.h> #include<iomanip> #include<stdlib.h> #include<iostream> #include<list> using namespace std; typedef int datatype; typedef struct BiTNode { datatype key = -1; /*关键字*/ struct BiTNode *lchild = NULL, *rchild = NULL; /*左、右子树*/ }BiTNode, *BiTree; /*二叉排序树的结点与指向根节点的指针*/ int SearchBST(BiTNode *T, datatype kx)/*查找*/ { BiTNode *p; p = T; if (p == NULL) { return 0; } if (p->key == kx) return 1; else if (p->key > kx) return SearchBST(p->lchild, kx); else return SearchBST(p->rchild, kx); } BiTNode * InsertBST(BiTNode *T, int kx)/*插入*/ { BiTNode *parent, *node, *child; /*树为空,创建根结点*/ if (T == NULL) { T = (BiTNode *)malloc(sizeof(BiTNode)); T->key = kx; T->lchild = NULL; T->rchild = NULL; return T; } parent = T;/*记录下根结点的位置*/ node = T; while (node != NULL) { /*待插数据存在,就返回*/ if (node->key == kx) { cout << "数据已经存在" << endl; return T; } else { parent = node; if (node->key < kx) node = node->rchild; else node = node->lchild; } } child = (BiTNode*)malloc(sizeof(BiTNode)); child->key = kx; child->lchild = NULL; child->rchild = NULL; if (kx > parent->key) parent->rchild = child; else parent->lchild = child; return T; } int DeleteBST(BiTree T, datatype value)/*删除*/ { BiTNode *p, *pre = NULL, *mid; p = T; if (T == NULL) return 0; /*找到该节点*/ while ((p != NULL) && (p->key != value)) { pre = p; if (p->key < value) { p = p->rchild; } else p = p->lchild; } if (p == NULL) return 0; /*至少有一个子节点为空*/ if ((p->lchild == NULL) || (p->rchild == NULL)) { if (pre->lchild == p) { pre->lchild = ((p->lchild == NULL) ? p->rchild : p->lchild); } else pre->rchild = ((p->lchild == NULL) ? p->rchild : p->lchild); free(p); /*释放节点*/ } else { /*删除的节点有2个子女*/ mid = p->rchild; pre = p; /*寻找右子树上的最小值的结点*/ while (mid->lchild != NULL) { pre = mid; mid = mid->lchild; } /*直接赋值,避免交换节点*/ p->key = mid->key; /*将mid节点的子节点作为pre的子节点,并将mid所指向的节点删除*/ if (pre->rchild == mid) pre->rchild = mid->rchild; else pre->lchild = mid->rchild; free(mid); } return 1; } void PrintBST(BiTree T)/*中序遍历输出*/ { if (T == NULL) return; PrintBST(T->lchild); printf("%d ", T->key); PrintBST(T->rchild); } void mainjiemian() { cout << " ★-----★---------★---------★-----★" << endl; cout << endl; cout << " ☆ 1 生成二叉排序树 ☆" << endl; cout << " 2 查找数据 " << endl; cout << " ☆ 3 删除数据 ☆" << endl; cout << " 4 退出 " << endl; cout << " ★-----★---------★---------★-----★" << endl; cout << endl; cout << endl; cout << "请选择数字命令:"; } void jieshu()//结束显示 { cout << " ★-----★---------★---------★-----★" << endl; cout << endl; cout << " ☆ 感谢您的使用! ☆" << endl; cout << endl; cout << " ★-----★---------★---------★-----★" << endl; cout << endl; } int main() { system("color 57"); char*end;/*末端指针*/ string order; mainjiemian(); int t; BiTNode *T = NULL; while (cin >> order) { int a_order = static_cast<int>(strtol(order.c_str(), &end, 10));/*将输入进来的值转化为int类型*/ switch (a_order + 48) { case'1': { system("cls"); printf("请输入要排序的数据:(以输入-1作为结束标志) "); while (scanf("%d", &t) != EOF) { if (t != -1) { T = InsertBST(T, t); } else break; } PrintBST(T); cout << endl; system("pause"); system("cls"); mainjiemian(); break; } case'2': { system("cls"); printf("请输入需要查找的数据: "); cin >> t; if (SearchBST(T, t)) { cout << "查找成功!" << endl; } else { cout << "查找失败!" << endl; } PrintBST(T); cout << endl; system("pause"); system("cls"); mainjiemian(); break; } case'3': { system("cls"); printf("请输入要删除的数据: "); cin >> t; if (DeleteBST(T, t)) { cout << "删除成功!" << endl; } else { cout << "数据不存在,删除失败!" << endl; } PrintBST(T); cout << endl; system("pause"); system("cls"); mainjiemian(); break; } case'4': { system("cls"); jieshu(); return 0; break; } default: { cin.clear(); cin.sync(); cout << "输入错误,重新返回主界面。" << endl; system("pause"); system("cls"); mainjiemian(); break; } } } cout << endl; //printf(" %d %s ", T->key, SearchBST(T, 10) ? "yes" : "no"); return 0; }