算法第四版- 3.3

算法第四版- 3.3

1.红黑树

红黑树漫画
红黑树有点难。就先不讲了。。。

2.AVL树

AVL树漫画
AVL树的查找和BST一样。重点在于插入和删除时的保持平衡操作。

1)判断是否为平衡二叉树

LC110

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool isBalanced(TreeNode* root) {
     return height(root)>=0 ;
    }
    int height(TreeNode *root)
    {
        if(root==nullptr)
            return 0;
        int height_left=height(root->left);
        int height_right=height(root->right);
        if(height_left==-1 || height_right==-1 || abs(height_left-height_right)>1)
              return -1;
        else
             return 1+max(height_right,height_left);

    }
};

简单的递归。-1就是子树已经崩了,那上面也肯定要崩。

2)插入和删除

AVLTree的插入与删除
主要可以参考以上博客。把inline全删去就能跑。分离式编译用inline好像会出问题。
下面是测试代码和运行结果:

//main.cpp
#include <iostream>
#include "AVLTree.h"
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
	AVLTree tree1;
	vector<int> v1 = { 1,2,3,4,5 };
	random_shuffle(v1.begin(), v1.end());
	for (int i : v1) tree1.insert(i);
	tree1.inOrder();
	cout << endl;
	return 0;
}

在这里插入图片描述
中序遍历成功,random_shuffle为随机重排算法。
然后对AVLTree.h和AVLTree.cpp写了一点注释,配合小灰的漫画,便于理解。

//AVLTree.h
#pragma once
typedef int ElemType;

struct AVLTreeNode {
	ElemType val;
	int height;
	AVLTreeNode* left;
	AVLTreeNode* right;
	AVLTreeNode(const ElemType& _val = ElemType(), const int& _height = int(),
		AVLTreeNode* _left = nullptr, AVLTreeNode* _right = nullptr)
		: val(_val), height(_height), left(_left), right(_right) {}
};

class AVLTree {
public:
	AVLTree(void) { root = nullptr; }
	~AVLTree(void) { clear(root); }

	void insert(const ElemType&);
	void erase(const ElemType&);

	void inOrder(void) { inOrder(root); }

private:
    AVLTreeNode* rotateRR(AVLTreeNode*);
	AVLTreeNode* rotateRL(AVLTreeNode*);
	AVLTreeNode* rotateLR(AVLTreeNode*);
	AVLTreeNode* rotateLL(AVLTreeNode*);
	AVLTreeNode* insert(AVLTreeNode*, const ElemType&);
	AVLTreeNode* erase(AVLTreeNode*, const ElemType&);
	int getHeight(AVLTreeNode*);
	void clear(AVLTreeNode*);
	void inOrder(AVLTreeNode*);

private:
	AVLTreeNode* root;

};

下面是cpp代码

//AVLTree.cpp
#include <algorithm>
#include <iostream>
#include "AVLTree.h"

void AVLTree::insert(const ElemType& val) {
	root = insert(root, val);
}

void AVLTree::erase(const ElemType& val) {
	root = erase(root, val);
}
//这个对应的是LL局面
AVLTreeNode* AVLTree::rotateRR(AVLTreeNode* node) {  //node为A节点
	AVLTreeNode* child = node->left;    //child为B节点
	AVLTreeNode* rGrandchild = child->right;    //rGrandchild为3号节点
	child->right = node;       //把A接到B的右边
	node->left = rGrandchild;   //把3号节点接到A的左边
	node->height = 1 + std::max(getHeight(node->left), getHeight(node->right));
	child->height = 1 + std::max(getHeight(node), getHeight(child->left));  //max的两个参数为A和C
	return child;  //B节点变为根节点
}

//这个对应于RL局面
 AVLTreeNode* AVLTree::rotateRL(AVLTreeNode* node) {
	node->right = rotateRR(node->right);   //对B进行右旋,转化为RR局面
	return rotateLL(node);       //对A节点左旋
}

 //这个对应于LR局面
AVLTreeNode* AVLTree::rotateLR(AVLTreeNode* node) {
	node->left = rotateLL(node->left);  //对B节点进行左旋,转化为LL局面
	return rotateRR(node);   //现在是LL局面,对A节点进行右旋
}

//这个对应的是RR局面
AVLTreeNode* AVLTree::rotateLL(AVLTreeNode* node) {   //node为A节点
	AVLTreeNode* child = node->right;      //child为B节点
	AVLTreeNode* lGrandchild = child->left;    //lGrandchild为2号节点
	child->left = node;            //把A节点安到B的左边
	node->right = lGrandchild;     //把2号节点安到A的右边
	node->height = 1 + std::max(getHeight(node->left), getHeight(node->right));
	child->height = 1 + std::max(getHeight(node), getHeight(child->right));
	return child;  //B节点变为根节点
}

//先插入节点,然后发现不平衡了,一步步往上走的过程中进行调整
AVLTreeNode* AVLTree::insert(AVLTreeNode* node, const ElemType& val) {
	if (nullptr == node) {
		node = new AVLTreeNode(val);
	}
	else if (node->val < val) {
		node->right = insert(node->right, val);
	}
	else {
		node->left = insert(node->left, val);
	}
	node->height = 1 + std::max(getHeight(node->left), getHeight(node->right));
	if (getHeight(node->left) - getHeight(node->right) >= 2) {  //node为4号节点
		if (node->left->val < val) {
			node = rotateLR(node);
		}
		else {    //显然2>1,进行右旋
			node = rotateRR(node);
		}
	}
	else if (getHeight(node->right) - getHeight(node->left) >= 2) {
		if (node->right->val < val) {
			node = rotateLL(node);
		}
		else {
			node = rotateRL(node);
		}
	}
	return node;
}

AVLTreeNode* AVLTree::erase(AVLTreeNode* node, const ElemType& val) {
	if (nullptr == node) {
		return nullptr;
	}
	//找到目标节点
	if (val == node->val) {
		if (nullptr == node->left) {
			AVLTreeNode* tmp = node;
			node = node->right;
			delete tmp;
			return node;
		}
		else if (nullptr == node->right) {
			AVLTreeNode* tmp = node;
			node = node->left;
			delete tmp;
			return node;
		}
		else {  //比如要删除2,左右节点均不为空
			AVLTreeNode* tmp = node->right;  //tmp=4
			while (tmp->left) {   //右子树的最小节点,即在子树中中序排序后删除的节点的右一位,tmp为最小的节点3
				tmp = tmp->left;
			}
			node->val = tmp->val;   //把2的值改为3
			node->right = erase(node->right, tmp->val);  //删除3节点
		}
	}
	//没有找到目标节点
	else if (node->val < val) {
		node->right = erase(node->right, val);
	}
	else {
		node->left = erase(node->left, val);
	}
	//这个时候已经删好了,开始调整高度
	node->height = 1 + std::max(getHeight(node->left), getHeight(node->right));
	if (getHeight(node->left) - getHeight(node->right) >= 2) {
		if (getHeight(node->left->left) > getHeight(node->left->right)) {
			node = rotateLR(node);
		}
		else {
			node = rotateRR(node);
		}
	}
	else if (getHeight(node->right) - getHeight(node->left) >= 2) {
		if (getHeight(node->right->right) > getHeight(node->right->left)) {
			node = rotateLL(node);
		}
		else { //显然0<1,走这条路,先右旋再左旋。
			node = rotateRL(node);
		}
	}
	return node;
}

int AVLTree::getHeight(AVLTreeNode* node) {
	return nullptr == node ? -1 : node->height;
}

void AVLTree::inOrder(AVLTreeNode* node) {
	if (nullptr == node) {
		return;
	}
	inOrder(node->left);
	// output
	std::cout << node->val;
	inOrder(node->right);
}

void AVLTree::clear(AVLTreeNode* node) {
	if (nullptr != node) {
		clear(node->left);
		clear(node->right);
		delete node;
		node = nullptr;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值