AVL樹的C++實現
基於前兩篇博文:
可以寫出AVL的C++實現如下:
首先是AVL樹的定義:
File avltree.h
class AVLTree {
public:
struct node;
typedef struct node* NodePointer;
AVLTree(int d);
void init(int d);
//LL單旋轉
NodePointer singleRotateLeft(NodePointer p);
//RR單旋轉
NodePointer singleRotateRight(NodePointer p);
//LR雙旋轉
NodePointer doubleRotateLeft(NodePointer p);
//RL雙旋轉
NodePointer doubleRotateRight(NodePointer p);
//插入值爲data的新結點
NodePointer insert(int data);
//在給定結點p插入值爲data的新結點
NodePointer insert(NodePointer p,int data);
//二叉樹結點尋找
NodePointer& find(int data);
//打印出當前AVL樹
void print();
//取得給定AVL樹結點高度
int height(NodePointer p);
//取得整棵AVL樹高度
int height();
void printDetail();
private:
void printDetail(NodePointer p,NodePointer parent);
NodePointer headNode;
//定義AVL結點,注意每個結點有一個height域表示當前結點高度,方便高度計算與查詢
struct node {
int data;
struct node* left, * right;
int height;
};
};
然後是AVL樹操作的具體實現:
File avltree.cpp
#include "avltree.h"
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <queue>
#include <stack>
#include <algorithm>
#include <stdexcept>
AVLTree::AVLTree(int d):headNode((NodePointer)malloc(sizeof(struct node)))
{
init(d);
}
void AVLTree::init(int d)
{
memset(headNode, 0, sizeof(struct node));
headNode->data = d;
}
//LL單旋轉
AVLTree::NodePointer AVLTree::singleRotateLeft(NodePointer p)
{
NodePointer q = p->left; //備份當前結點指針的左子樹指針
p->left = q->right; //將備份指針指向的結點的右子樹指針賦給當前結點的左指針
q->right = p;//將當前結點指針賦給備份指針的右指針
//更新左右子樹的高度信息
p->height=(std::max(height(p->left), height(p->right)) + 1);
q->height = (std::max(height(q->left), height(q->right)) + 1);
//返回新的結點指針爲備份的指針
return q;
}
//RR單旋轉
AVLTree::NodePointer AVLTree::singleRotateRight(NodePointer p)
{
NodePointer q = p->right;//備份當前結點指針的右子樹指針
p->right = q->left;//將備份指針指向的結點的左子樹指針賦給當前結點的右指針
q->left = p;//將當前結點指針賦給備份指針的左指針
//更新左右子樹的高度信息
p->height = (std::max(height(p->left), height(p->right)) + 1);
q->height = (std::max(height(q->left), height(q->right)) + 1);
//返回新的結點指針爲備份的指針
return q;
}
//LR雙旋轉
AVLTree::NodePointer AVLTree::doubleRotateLeft(NodePointer p)
{
p->left = singleRotateRight(p->left);//對當前結點的左兒子進行RR單旋轉
p = singleRotateLeft(p);//對當前結點進行LL單旋轉
return p;//返回旋轉後結果
}
//RL雙旋轉
AVLTree::NodePointer AVLTree::doubleRotateRight(NodePointer p)
{
p->right = singleRotateLeft(p->right);//對當前結點的右兒子進行LL單旋轉
p = singleRotateRight(p);//對當前結點進行RR單旋轉
return p;//返回旋轉後結果
}
AVLTree::NodePointer AVLTree::insert(int data)
{
//調用函數,從根節點開始插入
headNode = insert(headNode, data);
return headNode;
}
AVLTree::NodePointer AVLTree::insert(NodePointer p, int data)
{
//p == NULL 說明當前結點指針指向需要插入結點的位置,直接生成新結點,並返回
if (p == NULL)
{
p = (NodePointer)malloc(sizeof(struct node));
if (!p)
throw std::runtime_error("Memory out of space");
else {
p->left = p->right = 0;
p->height = 0;
p->data = data;
return p;
}
}//如果待插入的結點應該插入到左兒子上
else if (data < p->data)
{
p->left=insert(p->left, data);//執行插入
if (height(p->left) - height(p->right) == 2)//如果插入後該節點失衡,注意,平衡時左右子樹高度差1,插入一個結點引起的失衡左右子樹高度必定差2
{
if (data < p->left->data)//如果待插入結點應該插入到左兒子的左子樹(LL),執行LL單旋轉
p = singleRotateLeft(p);
else
//否則待插入結點必定會被插入到左兒子的右子樹(LR),執行LR雙旋轉
p = doubleRotateLeft(p);
}
}
//如果待插入的結點應該插入到右兒子上
else if (data > p->data)
{
p->right = insert(p->right, data);//插入哇
if (height(p->right) - height(p->left) == 2)
{
//如果待插入結點應該插入到右兒子的右子樹(RR),執行RR單旋轉
if (data > p->right->data)
p = singleRotateRight(p);
else
//否則待插入結點必定會被插入到右兒子的左子樹(RL),執行RL雙旋轉
p = doubleRotateRight(p);
}
}
p->height = std::max(height(p->left), height(p->right)) + 1;
return p;
}
//很普通的查找函數,,,,,,,,,,,
AVLTree::NodePointer& AVLTree::find(int data)
{
NodePointer &p = headNode;
while (p)
{
if (data > p->data)
p = p->right;
else if (data < p->data)
p = p->left;
else
break;
}
return p;
}
//以下是我寫的平淡無奇的輔助函數,,,不用看了
//,,,,,,,,,,,,,,,,,,,我寫的很爛的,,,,,,
void AVLTree::print()
{
using namespace std;
queue<NodePointer> q;
q.push(headNode);
while (!q.empty()) {
NodePointer p = q.front();
q.pop();
cout << p->data << " ";
if (p->left)
q.push(p->left);
if (p->right)
q.push(p->right);
}
cout << endl;
}
//說你呢,,,,你還看???
int AVLTree::height(NodePointer p)
{
if (!p)
return -1;
else
return p->height;
}
int AVLTree::height()
{
return height(headNode);
}
//嗚嗚放我一馬吧,,,,真的寫的很爛,,,,,
void AVLTree::printDetail()
{
std::cout << "=======INFO=======" << std::endl;
std::cout << "Height: " << height() << "\nDetail:\n";
printDetail(headNode, nullptr);
}
void AVLTree::printDetail(NodePointer p, NodePointer parent)
{
if (!p)
return;
if (parent && parent->left == p)
std::cout << parent->data << "-L->" << p->data << std::endl;
else if (parent && parent->right == p)
std::cout << parent->data << "-R->" << p->data << std::endl;
else if(parent == nullptr)
std::cout << "[ROOT]:" << p->data << std::endl;
printDetail(p->left, p);
printDetail(p->right, p);
}
//好吧你贏了QAQ,你看到了最後wwwwwww