#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -1
typedef int Status;
typedef int KeyType;
typedef struct RcdType {
KeyType key;
}RcdType;
typedef struct BBSTNode {
RcdType data;
int height;
struct BBSTNode* lchild, *rchild;
}BBSTNode, * BBSTree;
int max(int i, int j) {
return (i > j) ? i : j;
}
Status InitAVL(BBSTree& T) {
T = NULL;
return OK;
}
void DestroyBBST(BBSTree& T) {
//采用递归的方法后序遍历平衡二叉树,访问结点时销毁该结点。
if (NULL != T) {
DestroyBBST(T->lchild);
DestroyBBST(T->rchild);
free(T);
}
}
void Preorder(BBSTree& T){
//先序遍历
if (NULL != T) {
printf("%d ", T->data.key);
Preorder(T->lchild);
Preorder(T->rchild);
}
}
void Postorder(BBSTree& T){
//后序遍历
if (NULL != T) {
Postorder(T->lchild);
Postorder(T->rchild);
printf("%d ", T->data.key);
}
}
void Inorder(BBSTree& T){
//中序遍历
if (NULL != T) {
Inorder(T->lchild);
printf("%d ", T->data.key);
Inorder(T->rchild);
}
}
void JudgeBBST(BBSTree& T, Status &ok_error) {
//判断一棵树是否为平衡二叉树
if (NULL != T && ok_error) {
JudgeBBST(T->lchild, ok_error);
JudgeBBST(T->rchild, ok_error);
if (T->lchild->height - T->rchild->height >= 2 || T->rchild->height - T->lchild->height >= 2) {
ok_error = ERROR;
}
}
}
void LL_rotate(BBSTree& T) {
BBSTree lc;
lc = T->lchild;
int lclcH = lc->lchild->height;
int lcrcH = lc->rchild->height;
int rcH = T->rchild->height;//先把高度储存起来
T->lchild = lc->rchild;
lc->rchild = T;
T = lc;//完成变换
T->rchild->height = max(lcrcH, rcH) + 1;
T->height = max(lclcH, T->rchild->height) + 1;//完成高度修改
}
void RR_rotate(BBSTree& T) {
BBSTree rc;
rc = T->rchild;
int lcH = T->lchild->height;
int rclcH = rc->lchild->height;
int rcrcH = rc->rchild->height;//先把高度储存起来
T->rchild = rc->lchild;
rc->lchild = T;
T = rc;//完成变换
T->lchild->height = max(lcH, rclcH) + 1;
T->height = max(rcrcH, T->lchild->height) + 1;//完成高度修改
}
void LR_rotate(BBSTree& T) {
RR_rotate(T->lchild);
LL_rotate(T);
}
void RL_rotate(BBSTree& T) {
LL_rotate(T->rchild);
RR_rotate(T);
}
void InsertAVL(BBSTree& T, RcdType e,Status &ok_error) {
//结束:到达叶子,或已有该值结点存在则不插入
//分解:插入的值小于当前结点左递归插入,大于则右递归插入
//组合:在逐层回溯的时候,调整平衡
if (NULL == T) {
T = (BBSTree)malloc(sizeof(BBSTNode));
T->data = e;
T->height = 1;
T->lchild = T->rchild = NULL;
ok_error = OK;
}
else if (T->data.key == e.key) ok_error = ERROR;
else if (e.key < T->data.key) {
InsertAVL(T->lchild, e, ok_error);
if (T->lchild->height - T->rchild->height == 2) {
if (e.key < T->lchild->data.key) LL_rotate(T);
else LR_rotate(T);
}
else T->height = max(T->lchild->height, T->rchild->height) + 1;
}
else if (e.key > T ->data.key) {
InsertAVL(T ->rchild, e, ok_error);
if (T->rchild->height - T->lchild->height == 2) {
if (e.key > T->rchild->data.key) RR_rotate(T);
else RL_rotate(T);
}
else T->height = max(T->lchild->height, T->rchild->height) + 1;
}
}
void L_rotate(BBSTree& T) {
if (T->lchild->rchild->height > T->lchild->lchild->height) {
LR_rotate(T);
}
else LL_rotate(T);
}
void R_rotate(BBSTree& T) {
if (T->rchild->lchild->height > T->rchild->rchild->height) {
RL_rotate(T);
}
else RR_rotate(T);
}
RcdType find_maxleft(BBSTree lc) {
//用于在当前要删除结点左右子树都不为空且左子树高或一样高,的情况下找到当前要删除结点直接前驱
while (NULL != lc->rchild) {
lc = lc->rchild;
}
return lc->data;
}
RcdType find_minright(BBSTree rc) {
//用于在当前要删除结点左右子树都不为空且右子树高,的情况下找到当前要删除结点直接后驱
while (NULL != rc->lchild) {
rc = rc ->lchild;
}
return rc->data;
}
void DeleteAVL(BBSTree& T, RcdType e, Status& ok_error, Status& can_end) {
//结束:找到要删的结点,或到NULL结点
//分解:要删的结点小于当前结点,左递归删除,大于则右递归删除
//组合:从被删结点的“父节点”开始,逐层回溯,检查是否不平衡;若不平衡则调整,到根结点,或“调整后树的高度没有变化”就结束。
if (NULL == T) {
ok_error = ERROR;
can_end = TRUE;
}
else if (T->data.key == e.key) {
if (NULL == T->rchild) {//叶子结点,和仅右子树为空的情况
BBSTree temp = T;
T = T->lchild;
free(temp);
ok_error = OK;
}
else if (NULL == T->lchild) {//仅左子树为空的情况
BBSTree temp = T;
T = T->rchild;
free(temp);
ok_error = OK;
}
else {//左右结点都不为空的情况
if (T->lchild->height >= T->rchild->height) {
RcdType temp_e;
temp_e = find_maxleft(T->lchild);
T->data = temp_e;//仅赋值,属于“假删除”
Status can_end_temp = FALSE;
DeleteAVL(T->lchild, temp_e, ok_error, can_end_temp);
T->height = max(T->lchild->height, T->rchild->height) + 1; //及时调整高度,否则回溯到父节点
}
else {
RcdType temp_e;
temp_e = find_minright(T->rchild);
T->data = temp_e;//仅赋值,属于“假删除”
Status can_end_temp = FALSE;
DeleteAVL(T->rchild, temp_e, ok_error, can_end_temp);
T->height = max(T->lchild->height, T->rchild->height) + 1;//及时调整高度,否则回溯到父节点
}
}
}
else if (e.key < T->data.key) {
DeleteAVL(T->lchild, e, ok_error, can_end);
if(!can_end){
if (T->rchild->height - T->lchild->height == 2) {
R_rotate(T);
}
else { //如果调整之后当前结点高度没有变化,则不必要向上回溯调整
int old_height = T->height;
T->height = max(T->lchild->height, T->rchild->height) + 1;
can_end = (old_height == T->height) ? TRUE : FALSE;
}
}
}
else {
DeleteAVL(T->rchild, e, ok_error, can_end);
if (!can_end) {
if (T->lchild->height - T->rchild->height == 2) {
L_rotate(T);
}
else { //如果调整之后当前结点高度没有变化,则不必要向上回溯调整
int old_height = T->height;
T->height = max(T->lchild->height, T->rchild->height) + 1;
can_end = (old_height == T->height) ? TRUE : FALSE;
}
}
}
}
BBSTree SearchBBST(BBSTree T, KeyType key) {
//在平衡二叉树中查找某个值
if (NULL == T) return NULL;
else if (T->data.key == key) return T;
else if (key < T->data.key) return SearchBBST(T->lchild, key);
else return SearchBBST(T->rchild, key);
}
int main()
{
BBSTree T;
InitAVL(T);
Status ok_error = OK;
Status can_end = FALSE;
RcdType e; e.key = 0;
int search_key = 0;
int do_index = 0;
int go_flag = 1;
//在提示输入要操作的序号时,1表示插入,2表示删除,3表示对当前树三种遍历
//4表示查找一个值是否存在
//在插入或删除操作时,如果要输入一系列值,每个数字之间要以‘/’隔开
//例如:4/5/6/7/8(回车),最后一个数字后直接回车,不要加斜杠
while (go_flag){
printf("请输入要进行的操作的序号:");
scanf("%d", &do_index);
switch (do_index) {
case 1:{
while (scanf("%d", &e.key)) {
InsertAVL(T, e, ok_error);
if (ok_error == OK) printf("成功插入%d\n",e.key);
else printf("插入%d失败\n", e.key);
if('/' != getchar()) break;
}
break;
}
case 2:{
while (scanf("%d", &e.key)) {
DeleteAVL(T, e, ok_error, can_end);
if (ok_error == OK) printf("成功删除%d\n", e.key);
else printf("删除%d失败\n", e.key);
can_end = FALSE;
if('/' != getchar()) break;
}
break;
}
case 3:{
printf("inorder:");
Inorder(T);
printf("\n");
printf("preorder:");
Preorder(T);
printf("\n");
printf("postorder:");
Postorder(T);
printf("\n");
break;
}
case 4:{
BBSTree T1;
printf("请输入要查找的key值:");
scanf("%d", &search_key);
T1 = SearchBBST(T, search_key);
if(NULL != T1) printf("查找成功\n");
else printf("查找失败\n");
break;
}
}
printf("想继续这个程序吗(1 or 0):");
scanf("%d", &go_flag);
}
DestroyBBST(T);
}