潛析AVL樹--AVL樹的C++實現

AVL樹的C++實現

基於前兩篇博文:

簡析AVL樹–AVL樹的概念及單旋轉

潛析AVL樹–AVL樹的雙旋轉

可以寫出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
發佈了16 篇原創文章 · 獲贊 2 · 訪問量 6988
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章