本例子分为3个文件。
类声明头文件 hAVL.h #ifndef AVLTREE_H_INCLUDED #define AVLTREE_H_INCLUDED//AVL树数据结构定义 typedef int ElementType;//AVL数节点包含数据类型//树节点 typedef struct AVLNode{ElementType element;//节点包含的数据元素AVLNode *left;//节点左子树AVLNode *right;//节点右子树int height;//节点所在的高度 }*AVLTree;//AVL tree类封装 class CAVLTree{ private://供内部调用的函数int getHeight(AVLTree);//求得树的高度void setHeight(AVLTree, int);//设置节点的高度值//单旋转:向右旋转 AVLTree SingleRightRotate(AVLTree);//单旋转:向左旋转 AVLTree SingleLeftRotate(AVLTree);//双旋转:左右 AVLTree DoubleRightRotate(AVLTree);//双旋转:右左 AVLTree DoubleLeftRotate(AVLTree);public://默认构造函数 CAVLTree();//析构函数~CAVLTree();//创建AVL树void createAVLTree(ElementType *data, int n);//插入节点 AVLTree insertNode(AVLTree T, ElementType val);//删除树中元素值等于某值的节点AVLTree deleteNode(AVLTree T, const ElementType val);//搜寻元素值等于某值的节点 AVLTree searchNode(AVLTree, ElementType);//前序遍历输出树void preOrder(AVLTree T);//得到树中的元素值最大的节点 AVLTree getMaxNode(AVLTree);//得到树中的元素值最小的那个节点 AVLTree getMinNode(AVLTree);void deleteTree(AVLTree t);AVLTree T; };#endif // AVLTREE_H_INCLUDED
//右右外侧插入导致的不平衡,采用单旋转-左旋转进行修正 //参数解释:类实现文件AVLTr.cpp #include "stdafx.h" #include "hAVL.h"#include <iostream> #include <cmath> #include <math.h> #include <cassert>using namespace std;int fmax(int i, int j) {return i>j?i:j; };CAVLTree::CAVLTree() {T = NULL; }CAVLTree::~CAVLTree() {deleteTree(T); }//依据各元素的数据值,创建AVL树 void CAVLTree::createAVLTree(ElementType *data, int n) {if (T){cout << "The AVL Tree has been created" << endl;return;}if (!n)//元素序列为空 {T = NULL;return;}for (int i = 0; i < n; ++i){T = insertNode(T, *(data + i));}return; }AVLTree CAVLTree::insertNode(AVLTree T, ElementType val) {AVLNode *pNewNode = new AVLNode;pNewNode->element = val;pNewNode->left = NULL;pNewNode->right = NULL;pNewNode->height = 1;//新节点一定被插入在空节点的位置if (NULL == T){T = pNewNode;return T;}//需要插入节点的树非空//插入的元素已经存在于树中,不符合要求if (val == T->element){cout << "元素中有重复,构建AVL树失败!" << endl;return T;}//要插入的值小于根节点的值,将其插入左子树中if (val < T->element){//将其插入根节点的左子树中T->left = insertNode(T->left, val);//判断平衡条件是否仍然满足if (getHeight(T->left) - getHeight(T->right) > 1){//分两种情况进行旋转操作//插入点位于T的左子结点的左子树if (val < T->left->element)//实施单旋转-右旋转T = SingleRightRotate(T);else//插入点位于T的左子结点的右子树,实施双右旋转T = DoubleRightRotate(T);}}//要插入的值大于根节点的值,将其插入右子树中if (val > T->element){T->right = insertNode(T->right, val);//判断平衡条件是否仍然满足if (getHeight(T->right) - getHeight(T->left) > 1){//节点插入到T的右子节点的右子树中if (val > T->right->element)//实施单旋转-左旋转T = SingleLeftRotate(T);else//节点插入到T的右子节点的左子树上//实施双旋转-左旋转T = DoubleLeftRotate(T);}}//更新节点的height值setHeight(T, fmax(getHeight(T->left), getHeight(T->right)) + 1);return T; }AVLTree CAVLTree::deleteNode(AVLTree T, const ElementType val) {if (!T){cout << "The tree is NULL, delete failed" << endl;return T;}AVLTree searchedNode = searchNode(T, val);//没有找到相应的节点,删除失败if (!searchedNode){cout << "Cann't find the node to delete " << val << endl;return T;}//找到了需要删除的节点//需要删除的节点就是当前子树的根节点if (val == T->element){//左右子树都非空if (T->left && T->right){//在高度更大的那个子树上进行删除操作if (getHeight(T->left) > getHeight(T->right)){//左子树高度大,删除左子树中元素值最大的那个节点,同时将其值赋值给根节点T->element = getMaxNode(T->left)->element;T->left = deleteNode(T->left, T->element);}else{//删除右子树中元素值最小的那个节点,同时将其值赋值给根节点T->element = getMinNode(T->right)->element;T->right = deleteNode(T->right, T->element);}}else{//左右子树中有一个不为空,那个直接用需要被删除的节点的子节点替换之即可AVLTree oldNode = T;T = (T->left ? T->left : T->right);delete oldNode;//释放节点所占的空间oldNode = NULL;}}else if (val < T->element)//要删除的节点在左子树中 {//在左子树中进行递归删除T->left = deleteNode(T->left, val);//判断是否仍然满足平衡条件if (getHeight(T->right) - getHeight(T->left) > 1){if (T->right->left > T->right->right){//左双旋转T = DoubleLeftRotate(T);}else//进行左单旋转T = SingleLeftRotate(T);}else//满足平衡条件,需要更新高度信息T->height = fmax(getHeight(T->left), getHeight(T->right)) + 1;}else//需要删除的节点在右子树中 {T->right = deleteNode(T->right, val);//判断是否满足平衡条件if (getHeight(T->left) - getHeight(T->right) > 1){if (getHeight(T->left->right) > getHeight(T->left->left))//右双旋转T = DoubleRightRotate(T);else//右单旋转T = SingleRightRotate(T);}else//只需调整高度即可T->height = fmax(getHeight(T->left), getHeight(T->right)) + 1;}return T; }AVLTree CAVLTree::searchNode(AVLTree T, ElementType val) {if (!T){return NULL;}//搜索到if (val == T->element){return T;}else if (val < T->element){//在左子树中搜索return searchNode(T->left, val);}else{//在右子树中搜索return searchNode(T->right, val);} }void CAVLTree::preOrder(AVLTree T) {if (!T)cout << "NULL ";else{cout << T->element << " ";preOrder(T->left);preOrder(T->right);} }AVLTree CAVLTree::getMaxNode(AVLTree T) {if (!T)//树为空 {return NULL;}AVLTree tempNode = T;//向右搜寻直至右子节点为NULLwhile (tempNode->right){tempNode = tempNode->right;}return tempNode; }AVLTree CAVLTree::getMinNode(AVLTree T) {if (!T)//树为空 {return NULL;}AVLTree tempNode = T;//向左搜寻直至左子结点为NULLwhile (tempNode->left){tempNode = tempNode->left;}return tempNode; }int CAVLTree::getHeight(AVLTree T) {return (T == NULL) ? 0 : (T->height); }void CAVLTree::setHeight(AVLTree T, int height) {T->height = height; }//左左外侧插入导致的不平衡,采用单旋转-右旋转进行修正 //参数解释: //T:指向因某种操作失去平衡的最小子树根节点 AVLTree CAVLTree::SingleRightRotate(AVLTree T) {AVLTree xPNode = T;AVLTree yPNode = T->left;xPNode->left = yPNode->right;//更改原根节点的左子树yPNode->right = xPNode;//更改原根节点左孩子的右子树//更新进行了旋转操作的节点的高度xPNode->height = fmax(getHeight(xPNode->left), getHeight(xPNode->right)) + 1;yPNode->height = fmax(getHeight(yPNode->left), getHeight(yPNode->right)) + 1;//原根节点的左孩子节点成为新的根节点return yPNode;//T:指向因某种操作失去平衡的最小子树根节点 AVLTree CAVLTree::SingleLeftRotate(AVLTree T) {AVLTree xPNode = T;AVLTree yPNode = T->right;xPNode->right = yPNode->left;//更改原根节点的右孩子yPNode->left = xPNode;//提升原根节点的右孩子节点为新的根节点//更新执行了旋转操作的节点的高度信息xPNode->height = fmax(getHeight(xPNode->left), getHeight(xPNode->right)) + 1;yPNode->height = fmax(getHeight(yPNode->left), getHeight(yPNode->right)) + 1;//返回新的根节点return yPNode; }//插入点位于T的左子结点的右子树 AVLTree CAVLTree::DoubleRightRotate(AVLTree T) {//双旋转可以通过两次单旋转实现//第一次单旋转assert(T->left != NULL);//对其左子树进行一次单旋转-左旋转T->left = SingleLeftRotate(T->left);//第二次单旋转//对新产生的树进行一次单旋转-右旋转return SingleRightRotate(T); }//插入点位于T的右子节点的左子树 AVLTree CAVLTree::DoubleLeftRotate(AVLTree T) {//双旋转可以通过两次单旋转实现//第一次单旋转assert(T->right != NULL);//对其右子树进行一次单旋转-右旋转T->right = SingleRightRotate(T->right);//第二次单旋转//对新产生的树进行一次单旋转-左旋转return SingleLeftRotate(T); }void CAVLTree::deleteTree(AVLTree t) {if (NULL == t)return;deleteTree(t->left);deleteTree(t->right);delete t;t = NULL; }
主函数文件 main.cpp // AVLTree.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h"//平衡二叉树搜索树(AVL tree-Adelson-Velskii-Landis tree)编程实现 #include "hAVL.h" #include <iostream> using namespace std;int main() {// 通过给定序列创建平衡二叉树const int NumElements = 8;cout << "AVL树各项操作编程实现:" << endl;int a[NumElements] = { 25,2,64,45,12,34,9,18};CAVLTree *CAVLTreeObj1 = new CAVLTree();CAVLTreeObj1->createAVLTree(a, NumElements);cout << "AVL Tree先序遍历结果:" << endl;CAVLTreeObj1->preOrder(CAVLTreeObj1->T);cout << endl;// 插入一个新的数据int insertedVal1 = 15;CAVLTreeObj1->T = CAVLTreeObj1->insertNode(CAVLTreeObj1->T, insertedVal1);cout << "向AVL树中插入元素 " << insertedVal1 << "之后的先序遍历结果:" << endl;CAVLTreeObj1->preOrder(CAVLTreeObj1->T);cout << endl << endl;// 在插入一个新的数据(由重复数据情况下)int insertedVal2 = 16;CAVLTreeObj1->T = CAVLTreeObj1->insertNode(CAVLTreeObj1->T, insertedVal2);cout << "向AVL树中插入元素 " << insertedVal2 << "之后的先序遍历结果:" << endl;CAVLTreeObj1->preOrder(CAVLTreeObj1->T);cout << endl << endl;// 寻找最小的元素int minVal = CAVLTreeObj1->getMinNode(CAVLTreeObj1->T)->element;cout << "树中最小的元素是:" << minVal << endl;cout << endl;// 寻找最大的元素int maxVal = CAVLTreeObj1->getMaxNode(CAVLTreeObj1->T)->element;cout << "树中最大的元素是:" << maxVal << endl;cout << endl;// 删除1个元素const int deletedVal1 = 11;CAVLTreeObj1->T = CAVLTreeObj1->deleteNode(CAVLTreeObj1->T, deletedVal1);cout << "删除元素值为 " << deletedVal1 << "的节点之后的树先序遍历结果:" << endl;CAVLTreeObj1->preOrder(CAVLTreeObj1->T); cout << endl << endl;// 删除第2个元素const int deletedVal2 = 20;CAVLTreeObj1->T = CAVLTreeObj1->deleteNode(CAVLTreeObj1->T, deletedVal2);cout << "删除元素值为 " << deletedVal2 << "的节点之后的树先序遍历结果:" << endl;CAVLTreeObj1->preOrder(CAVLTreeObj1->T);cout << endl << endl;// 删除第3个元素const int deletedVal3 = 18;CAVLTreeObj1->T = CAVLTreeObj1->deleteNode(CAVLTreeObj1->T, deletedVal3);cout << "删除元素值为 " << deletedVal3 << "的节点之后的树先序遍历结果:" << endl;CAVLTreeObj1->preOrder(CAVLTreeObj1->T);cout << endl << endl;const int searchedVal1 = 12;AVLTree searchedPNode = CAVLTreeObj1->searchNode(CAVLTreeObj1->T, searchedVal1);if (!searchedPNode)cout << "cannot find such node whose elemen equals " << searchedVal1 << endl;elsecout << "search success element " << searchedVal1 << endl;const int searchedVal2 = 13;searchedPNode = CAVLTreeObj1->searchNode(CAVLTreeObj1->T, searchedVal2);if (!searchedPNode)cout << "cannot find such node whose elemen equals " << searchedVal2 << endl;elsecout << "search success element " << searchedVal2 << endl;cout << endl << endl;getchar();return 0; }