平衡二叉树实现--可验证题目

  1.   将关键字(DEC, FEB, NOV, OCT, JUL, SEP, AUG, APR, MAR, MAY, JUN, JAN)按字母顺序依次插入到一棵初始为空的AVL树中,画出每插入一个关键字后的AVL树,并标明平衡旋转的类型。在所建立的AVL树中删除关键字MAY,为保持AVL树的特性,应如何进行删除和调整? 若接着删除关键字FEB,又应如何删除与调整?
// AVLTree.cpp: 定义控制台应用程序的入口点。
//平衡二叉树
//
 
#include<stdio.h>
#include<stdlib.h>
#include<stack>
#include<queue>
#include<string>
#include<iostream>
using namespace std;
 
 
typedef int dataType;
 
#define EH 0       //左右子树一样高
#define LH 1       //左子树比右子树高
#define RH -1      //右子树比左子树高
 
 
//定义节点结构
typedef struct Node {
	dataType keyValue;             //数据
	int BalanceFactor;             //平衡因子
	struct Node *leftChild, *rightChild;
}*PNode;
 
 
//为新建一个节点
PNode createNode(dataType keyValue) {
	PNode newNode = (PNode)malloc(sizeof(Node));
	newNode->keyValue = keyValue;
	newNode->BalanceFactor = EH;
	newNode->leftChild = NULL;
	newNode->rightChild = NULL;
	return newNode;
}
 
 
//右旋 顺时针旋转
void R_Rotate(PNode* node) {
	PNode tmp = (*node)->leftChild;
	(*node)->leftChild = tmp->rightChild;
	tmp->rightChild = (*node);
    (*node) = tmp;
}
 
//左旋,逆时针旋转
void L_Rotate(PNode* node) {
	PNode tmp = (*node)->rightChild;
	(*node)->rightChild = tmp->leftChild;
	tmp->leftChild = (*node);
	(*node) = tmp;
}
 
//左边失衡调整
void leftBalance(PNode* node) {
	PNode leftchild = (*node)->leftChild;
	PNode tmpRightChild = NULL;
	switch (leftchild->BalanceFactor) 
	{
	case LH:                                                                     //LL型失衡
		(*node)->BalanceFactor = leftchild->BalanceFactor = EH;
		 R_Rotate(node);
		 break;
	case RH:                                                                    //LR型失衡
		tmpRightChild = leftchild->rightChild;
		switch (tmpRightChild->BalanceFactor)
		{
		case LH:
			(*node)->BalanceFactor = RH;
			leftchild->BalanceFactor = EH;
			break;
		case EH:
			(*node)->BalanceFactor = leftchild->BalanceFactor = EH;
			break;
		case RH:
			(*node)->BalanceFactor = EH;
			leftchild->BalanceFactor = LH;
			break;
		}
		tmpRightChild->BalanceFactor = EH;
		L_Rotate(&(*node)->leftChild);
		R_Rotate(node);
		break;
	}
}
 
 
//右边失衡调整
void rightBalance(PNode* node) {
	PNode rightchild = (*node)->rightChild;
	PNode tmpChild = NULL;
	switch (rightchild->BalanceFactor)
	{
	case RH:                                                                          //RR型失衡
		(*node)->BalanceFactor = rightchild->BalanceFactor = EH;
		L_Rotate(node);
		break;
	case LH:                                                                         //RL型失衡
		tmpChild = rightchild->leftChild;
		switch (tmpChild->BalanceFactor)
		{
		case LH:
			(*node)->BalanceFactor = EH;
			rightchild->BalanceFactor = RH;
			break;
		case EH:
			(*node)->BalanceFactor = rightchild->BalanceFactor = EH;
			break;
		case RH:
			(*node)->BalanceFactor = EH;
			rightchild->BalanceFactor = LH;
			break;
		}
		tmpChild->BalanceFactor = EH;
		R_Rotate(&(*node)->rightChild);
		L_Rotate(node);
		break;
	}
}
 
 
//插入新值,higher用于判定是否需要调整平衡因子
int InsertKeyValue(PNode* node, dataType keyValue,bool* higher) {
	if ((*node) == NULL) {                                    //树中不包含此键值,则新建一个节点,
		(*node) = createNode(keyValue);
		*higher=true;
	}
	else if ((*node)->keyValue == keyValue) {                //树中已经包含此键值,则不需要插入
		*higher = false;
		return 0;
	}
	else if (keyValue < (*node)->keyValue) {                  //插入到左子树中
		if (!InsertKeyValue(&(*node)->leftChild, keyValue, higher))   //如果左子树中存在该节点
			return 0;
		if (*higher) {   
			switch ((*node)->BalanceFactor)
			{
			case LH:
				leftBalance(node);
				*higher = false;
				break;
			case RH:
				(*node)->BalanceFactor = EH;
				*higher = false;
				break;
			case EH:
				(*node)->BalanceFactor = LH;
				*higher = true;
				break;
			}
		}
	}
	else {
		if (!InsertKeyValue(&(*node)->rightChild, keyValue,higher))   //如果右子树中存在该节点
			return 0;
		if (*higher) {
			switch ((*node)->BalanceFactor)
			{
			case LH:                                                  
				(*node)->BalanceFactor = EH;
				*higher = false;
				break;
			case RH:
				rightBalance(node);
				*higher = false;
				break;
			case EH:
				(*node)->BalanceFactor = RH;
				*higher = true;
				break;
			}
		}
	}
	return 1;
}
 
 
 
//按关系输出,便于检验数的构造是否正确
void printfTree(PNode root) {
	if (root) {
		if (root->leftChild) {
			printf("%d is %d's left child\n", root->leftChild->keyValue, root->keyValue);
			printfTree(root->leftChild);
		}
		if (root->rightChild) {
			printf("%d is %d's right child\n", root->rightChild->keyValue, root->keyValue);
			printfTree(root->rightChild);
		}
	}
}
 
/*=================================遍历:递归和非递归=========================*/
//中序--递归
void InorderTra(PNode root) {
	if (root) {
		InorderTra(root->leftChild);
		printf("%d\t", root->keyValue);
		InorderTra(root->rightChild);
	}
}
 
//中序--非递归
void InorderTra2(PNode root) {
	if (!root) {
		printf("树为空!\n");
	}
	stack<PNode> myStack;
	while (root|| !myStack.empty()) {      //找到最左边的节点,并将路径上的几点压入栈中
		while (root)
		{
			myStack.push(root);
			root = root->leftChild;
		}
		root = myStack.top();              //取栈顶的值
		myStack.pop();                     //从栈中删除
		printf("%d\t", root->keyValue);
		root=root->rightChild;
	}
	printf("\n");
}
 
 
 
//前序遍历
//前序--递归
void PreOrderTra(PNode root) {
	if (root != NULL) {
		printf("%d\t", root->keyValue);
		PreOrderTra(root->leftChild);
		PreOrderTra(root->rightChild);
	}
	
}
//前序--非递归
void PreOrderTra2(PNode root) {
	if (!root) {
		printf("树为空!\n");
	}
	stack<PNode> myStack;
	while (root || !myStack.empty()) {
		while (root)
		{
			myStack.push(root);
			printf("%d\t", root->keyValue);
			root = root->leftChild;
		}
		root = myStack.top();
		myStack.pop();
		root = root->rightChild;
	}
	printf("\n");
}
 
 
 
//后序遍历 
//后序--递归
void PostOrderTra(PNode root) {
	if (root) {
		PostOrderTra(root->leftChild);
		PostOrderTra(root->rightChild);
		printf("%d\t", root->keyValue);
	}
}
 
//后序--非递归
void PostOrderTra2(PNode root) {         
	int flag[30];         //用一个标记,标记右子树是否访问过
	stack<PNode> myStack;
	if (!root) {
		printf("树为空!\n");
		return;
	}
	while (root !=NULL ) {                             //首先将所有的左子树入栈
		myStack.push(root);
		flag[myStack.size()] = 0;
		root = root->leftChild;
	}
	while (!myStack.empty()) {
		root = myStack.top();
		if (root->rightChild&&flag[myStack.size()] == 0) {     //如果是第一次访问,则还不能输出,需要找到其右子树,将右子树入栈
			flag[myStack.size()] = 1;
			root = root->rightChild;
			while (root)
			{
				myStack.push(root);
				flag[myStack.size()] = 0;
				root = root->leftChild;
			}
		}
		root = myStack.top();                                  //第二次出栈,可以输出了
		printf("%d\t", root->keyValue);
		myStack.pop();
	}
	printf("\n");
}
 
 
 
//按层次遍历
//辅助函数,求树的最大深度
int getDeep(PNode root) {
	if (!root) {
		return 0;
	}
	int leftDeep = getDeep(root->leftChild) + 1;
	int rightDeep = getDeep(root->rightChild) + 1;
	return leftDeep > rightDeep ? leftDeep : rightDeep;
}
 
//输出指定的层,将根节点视为0层
int LevelOrderTra(PNode root,int level) {
	if (!root || level < 0) {
		printf("%s\t", "NULL");
		return 0;
	}
	if (level == 0) {
		printf("%d\t", root->keyValue);
		return 1;
	}
	return LevelOrderTra(root->leftChild, level - 1) + LevelOrderTra(root->rightChild, level - 1);
 
}
//从根节点开始打印出所有层
void printByLevel(PNode root, int deep) {
	for (int i = 0; i < deep; i++) {
		LevelOrderTra(root, i);
	}
	printf("\n");
}
//法2,利用队列,实现安层次遍历
void printByLevel2(PNode root) {
	if (!root) {
		printf("树为空!\n");
	}
	queue<PNode> myQueue;
	myQueue.push(root);
	while (!myQueue.empty()) {
		root = myQueue.front();
		myQueue.pop();
		printf("%d\t", root->keyValue);
		if (root->leftChild)myQueue.push(root->leftChild);
		if (root->rightChild) myQueue.push(root->rightChild);
	}
}
 
 
/*=====================查找===================*/
int SearchTree(PNode root, dataType key) {
	if (root->keyValue == key) {
		return 1;
	}
	else if (key > root->keyValue && root->rightChild) {
		return SearchTree(root->rightChild, key);
	}
	else if(key < root->keyValue && root->leftChild) {
		return SearchTree(root->leftChild, key);
	}
	else {
		return 0;
	}
}
 
/*=======================删除==================*/
bool delNode(PNode &root, dataType key,bool &shorter) {
	if (root == NULL) {
		return false;
	}
	else if (key == root->keyValue) {
		PNode tmp = NULL;
		if (root->leftChild == NULL) {
			tmp = root;
			root = root->rightChild;
			delete tmp;
			shorter = true;
		}
		else if (root->rightChild == NULL) {
			tmp = root;
			root = root->leftChild;
			delete tmp;
			shorter = true;
		}
		else {                                         
			tmp = root->leftChild;                              
			while (tmp->rightChild) {
				tmp = tmp->rightChild;
			}
			root->keyValue = tmp->keyValue;
			delNode(root->leftChild, tmp->keyValue, shorter);
		}
	}
	else if (key < root->keyValue) {
		if (!delNode(root->leftChild, key, shorter)) {
			return false;
		}
		if (shorter) {
			switch (root->BalanceFactor)
			{
			case LH: 
				root->BalanceFactor = EH;
				shorter = true;
				break;
			case RH:
				rightBalance(&root);
				if (root->rightChild->BalanceFactor == EH) {
					shorter = false;
				}
				else {
					shorter = true;
				}
				break;
			case EH:
				root->BalanceFactor = RH;
				shorter = false;
				break;
			}
		}
	}
	else {
		if (!delNode(root->rightChild, key, shorter)) {
			return false;
		}
		if (shorter) {
			switch (root->BalanceFactor)
			{
			case LH:
				leftBalance(&root);
				if (root->leftChild->BalanceFactor == EH) {
					shorter = false;
				}
				else {
					shorter = true;
				}
				break;
			case EH:
				root->BalanceFactor = LH;
				shorter = false;
				break;
			case RH:
				root->BalanceFactor = EH;
				shorter = true;
				break;
			}
		}
	}
	return true;
}
 
//void delNode2(PNode &root, dataType key) {
//	if (!root) {
//		printf("树为空!\n");
//		return;
//	}
//	else if (!SearchTree(root, key)) {
//		printf("树中不存在值为%d的节点\n", key);
//	}else{
//		PNode current = root;
//		while (current->keyValue != key) {
//			if (key < current->keyValue) current = current->leftChild;
//			else current = current->rightChild;
//		}
//		if (current->leftChild && current->rightChild) {
//			PNode minNode = current->rightChild;
//			while (minNode) {
//				minNode = minNode->leftChild;
//			}
//			current->keyValue = minNode->keyValue;
//			PNode tmp = minNode;
//			minNode = minNode->rightChild;
//			delete tmp;
//		}
//		else if (current->leftChild || current->rightChild) {
//			PNode tmp=current;
//			current = current->leftChild ? current->leftChild : current->rightChild;
//			delete tmp;
//		}
//		else {
//			PNode tmp=current;
//			current =NULL;
//			delete tmp;
//		}
//    }
//}
 
 
 
int main()
{
	  //将关键字(DEC, FEB, NOV, OCT, JUL, SEP, AUG, APR, MAR, MAY, JUN, JAN)按字
	string ts[12]={"DEC", "FEB", 
	"NOV", "OCT",
	"JUL","SEP",
	"AUG","APR",
	"MAR","MAY",
	"JUN","JAN"};
	sort(ts,ts+12);
	for(int i=0;i<12;i++)
	std::cout<<ts[i]<<std::endl;
	int i, dataArr[] = { 3,4,10,11,6,12,2,1,8,9,7,5};
	PNode treeRoot = NULL;
	bool heigher;
	for (i = 0; i < 12; i++) {
		InsertKeyValue(&treeRoot, dataArr[i],&heigher);
		printfTree(treeRoot);
		printf("\n\n");
	}
	
	/*printf("中序遍历是:");
	InorderTra(treeRoot);
	printf("\n");
	InorderTra2(treeRoot);*/
	/*printf("前序遍历是:");
	PreOrderTra(treeRoot);
	printf("\n");
	PreOrderTra2(treeRoot);*/
	/*printf("后序遍历是:");
	PostOrderTra(treeRoot);
	printf("\n");
	PostOrderTra2(treeRoot);*/
	/*printf("deep:%d\n", getDeep(treeRoot));*/
	printf("层次遍历是:");
	printByLevel(treeRoot, getDeep(treeRoot));
	printf("\n");
	/*printByLevel2(treeRoot);*/
	//测试查找
	/*while (true)
	{
		printf("请输入要查找的值:");
		int key;
		scanf("%d", &key);
		printf("\n查找结果:%d\n", SearchTree(treeRoot, key));
	}*/
	//测试删除
	while (true)
	{
		printf("请输入要删除的值:");
		int key;
		scanf("%d", &key);
		bool shoter = false;
		delNode(treeRoot, key,shoter);
		/*delNode2(treeRoot, key);*/
		printByLevel(treeRoot,4);
	}
    return 0;
}

https://blog.csdn.net/xwm1993/article/details/80405430

猜你喜欢

转载自blog.csdn.net/qiang_____0712/article/details/87906058
今日推荐