AVL树的递归和非递归插入、删除、查找等操作的C++实现(考虑平衡因子和树的高度)

27 篇文章 0 订阅
1 篇文章 0 订阅

AVL树根据平衡特性和二叉搜索树的特性递归实现插入、删除。

//
// Created by hpf on 18-6-21.
//

#ifndef AVLTREE_AVLTREE_H
#define AVLTREE_AVLTREE_H

#include <algorithm>
#include <iostream>
#include <vector>

template<typename Key, typename Value>
class AVLTree {
private:
    struct Node {
        Key key;
        Value value;
        Node *left;
        Node *right;
        int height;

        Node(Key key, Value value) {
            this->key = key;
            this->value = value;
            this->left = this->right = nullptr;
            height = 1;
        }

        Node(Node *node) {
            this->key = node->key;
            this->value = node->value;
            this->left = node->left;
            this->right = node->right;
            this->height = node->height;
        }
    };

    Node *root;
    int size;

public:

    AVLTree() {
        root = nullptr;
        size = 0;
    }

    ~AVLTree() {
        destroy(root);
    }

    int getSize() {
        return size;
    }

    int isEmpty() {
        return size == 0;
    }

    int getHeight(Node *node) {
        if (node == nullptr) {
            return 0;
        }
        return node->height;
    }

    int getBalanceFactor(Node *node) {
        if (node == nullptr) {
            return 0;
        }
        return getHeight(node->left) - getHeight(node->right);
    }

    bool isBST() {
        std::vector<Key> keys;
        inOrder(root, keys);
        for (int i = 1; i < keys.size(); ++i) {
            if (keys.at(i - 1) < keys.at(i)) {
                return false;
            }
        }
        return true;
    }

    bool isBalanced() {
        return isBalanced(root);
    }

    void add(Key key, Value value) {
        root = add(root, key, value);
    }

    bool contains(Key key) {
        return getNode(root, key) != nullptr;
    }

    Value *get(Key key) {
        Node *node = getNode(root, key);
        return node == nullptr ? nullptr : &(node->value);
    }

    void set(Key key, Value newValue) {
        Node *node = getNode(root, key);
        if (node != nullptr) {
            node->value = newValue;
        }
    }

    // 从二叉树中删除键值为key的节点
    Value *remove(Key key) {
        Node *node = getNode(root, key);
        if (node != nullptr) {
            root = remove(root, key);
            return &(node->value);
        }
        return nullptr;
    }

private:

    // 向以node为根的二叉搜索树中,插入节点(key, value)
    // 返回插入新节点后的二叉搜索树的根
    Node *add(Node *node, Key key, Value value) {
        if (node == nullptr) {
            size++;
            return new Node(key, value);
        }
        if (key == node->key) {
            node->value = value;
        } else if (key < node->key) {
            node->left = add(node->left, key, value);
        } else {
            node->right = add(node->right, key, value);
        }
        node->height = 1 + std::max(getHeight(node->left), getHeight(node->right));
        int balanceFactor = getBalanceFactor(node);

        if (balanceFactor > 1 && getBalanceFactor(node->left) >= 0) {
            return rightRotate(node);
        }

        if (balanceFactor < -1 && getBalanceFactor(node->right) <= 0) {
            return leftRotate(node);
        }

        if (balanceFactor > 1 && getBalanceFactor(node->left) < 0) {
            node->left = leftRotate(node->left);
            return rightRotate(node);
        }

        if (balanceFactor < -1 && getBalanceFactor(node->right) > 0) {
            node->right = rightRotate(node->right);
            return leftRotate(node);
        }

        return node;
    }

    // 在以node为根的二叉搜索树中查找key所对应的Node
    Node *getNode(Node *node, Key key) {
        if (node == nullptr) {
            return nullptr;
        }
        if (key == node->key) {
            return node;
        } else if (key < node->key) {
            return getNode(node->left, key);
        } else {
            return getNode(node->right, key);
        }
    }

    void destroy(Node *node) {
        if (node != nullptr) {
            destroy(node->left);
            destroy(node->right);
            delete node;
            size--;
        }
    }

    // 在以node为根的二叉搜索树中,返回最小键值的节点
    Node *minimum(Node *node) {
        if (node->left == nullptr)
            return node;
        return minimum(node->left);
    }

    // 在以node为根的二叉搜索树中,返回最大键值的节点
    Node *maximum(Node *node) {
        if (node->right == nullptr)
            return node;
        return maximum(node->right);
    }

    // 删除掉以node为根的二分搜索树中的最小节点
    // 返回删除节点后新的二分搜索树的根
    Node *removeMin(Node *node) {
        if (node->left == nullptr) {
            Node *rightNode = node->right;
            delete node;
            size--;
            return rightNode;
        }

        node->left = removeMin(node->left);
        return node;
    }

    // 删除掉以node为根的二分搜索树中的最大节点
    // 返回删除节点后新的二分搜索树的根
    Node *removeMax(Node *node) {
        if (node->right == nullptr) {
            Node *leftNode = node->left;
            delete node;
            size--;
            return leftNode;
        }

        node->right = removeMax(node->right);
        return node;
    }

    // 删除掉以node为根的二分搜索树中键值为key的节点
    // 返回删除节点后新的二分搜索树的根
    Node *remove(Node *node, Key key) {
        if (node == nullptr) {
            return nullptr;
        }

        Node *retNode;
        if (key < node->key) {
            node->left = remove(node->left, key);
            retNode = node;
        } else if (key > node->key) {
            node->right = remove(node->right, key);
            retNode = node;
        } else {
            if (node->left == nullptr) {
                Node *rightNode = node->right;
                delete node;
                size--;
                retNode = rightNode;
            } else if (node->right == nullptr) {
                Node *leftNode = node->left;
                delete node;
                size--;
                retNode = leftNode;
            } else {
                Node *successor = new Node(minimum(node->right));
                size++;

                successor->right = remove(node->right, successor->key);
                successor->left = node->left;

                delete node;
                size--;

                retNode = successor;
            }
        }
        if (retNode == nullptr) {
            return nullptr;
        }
        retNode->height = 1 + std::max(getHeight(retNode->left), getHeight(retNode->right));
        int balanceFactor = getBalanceFactor(retNode);

        if (balanceFactor > 1 && getBalanceFactor(retNode->left) >= 0) {
            return rightRotate(retNode);
        }

        if (balanceFactor < -1 && getBalanceFactor(retNode->right) <= 0) {
            return leftRotate(retNode);
        }

        if (balanceFactor > 1 && getBalanceFactor(retNode->left) < 0) {
            retNode->left = leftRotate(retNode->left);
            return rightRotate(retNode);
        }

        if (balanceFactor < -1 && getBalanceFactor(retNode->right) > 0) {
            retNode->right = rightRotate(retNode->right);
            return leftRotate(retNode);
        }

        return retNode;
    }

    void inOrder(Node *node, std::vector<Key> keys) {
        if (node == nullptr) {
            return;
        }
        inOrder(node->left, keys);
        keys.push_back(node->key);
        inOrder(node->right, keys);
    }

    bool isBalanced(Node *node) {
        if (node == nullptr) {
            return true;
        }

        int balanceFactor = getBalanceFactor(node);
        if (std::abs(balanceFactor) > 1) {
            return false;
        }

        return isBalanced(node->left) && isBalanced(node->right);
    }

    Node *leftRotate(Node *y) {
        Node *x = y->right;
        Node *tmp = x->left;
        x->left = y;
        y->right = tmp;
        y->height = std::max(getHeight(y->left), getHeight(y->right)) + 1;
        x->height = std::max(getHeight(x->left), getHeight(x->right)) + 1;
        return x;
    }

    Node *rightRotate(Node *y) {
        Node *x = y->left;
        Node *tmp = x->right;
        x->right = y;
        y->left = tmp;
        y->height = std::max(getHeight(y->left), getHeight(y->right)) + 1;
        x->height = std::max(getHeight(x->left), getHeight(x->right)) + 1;
        return x;
    }
};

#endif //AVLTREE_AVLTREE_H

 


AVL树的非递归实现插入和查找(根据平衡因子的判断)

四种旋转原则:

1、保持搜索树特性

2、左右相对平衡

#pragma once
#include<iostream>
#include<cassert>
#include<vector>

using namespace std;


template<class K,class V>
struct AVLTreeNode {
	pair<K, V>kv;
	AVLTreeNode<K, V>* left;
	AVLTreeNode<K, V>* right;
	AVLTreeNode<K, V>* parent;

	//右子树-左子树(高度差)
	int bf = 0;

	AVLTreeNode(const pair<K, V>& kv) :
		kv(kv), left(nullptr), right(nullptr), parent(nullptr),bf(0)
	{}

};

template<class K,class V>
class AVLTress {
	typedef AVLTreeNode<K, V> Node;
private:
	Node* root = nullptr;

	void RotateL(Node* parent) {
		Node* subR = parent->right;
		Node* subRL = subR->left;
		parent->right = subRL;
		if (subRL)
		{
			subRL->parent = parent;
		}
		subR->left = parent;
		Node* pparent = parent->parent;
		parent->parent = subR;
		if (parent == root)
		{
			root = subR;
			root->parent = nullptr;
		}
		else
		{
			if (parent == pparent->left)
			{
				pparent->left = subR;
			}
			else{
				pparent->right = subR;
			}
			subR->parent = pparent;
		}
		subR->bf = parent->bf = 0;
	}

	void RotateR(Node* parent) {
		Node* subL = parent->left;
		Node* subLR = subL->right;

		parent->left = subLR;
		if (subLR)
		{
			subLR->parent = parent;
		}
		Node* pparent = parent->parent;
		subL->right = parent;
		parent->parent = subL;
		if (parent == root)
		{
			root = subL;
			root->parent = nullptr;
		}
		else
		{
			if (parent == pparent->left)
			{
				pparent->left = subL;
			}
			else {
				pparent->right = subL;
			}
			subL->parent = pparent;
		}
		subL->bf = parent->bf = 0;
	}

	void RotateLR(Node* parent) {
		Node* subL = parent->left;
		Node* subLR = subL->right;
		int bf = subLR->bf;

		RotateL(parent->left);
		RotateR(parent);

		if (bf == 0)
		{
			subL->bf = 0;
			subLR->bf = 0;
			parent->bf = 0;
		}
		else if (bf == -1)
		{
			subL->bf = 0;
			subLR->bf = 0;
			parent->bf = 1;
		}
		else if (bf == 1) 
		{
			subL->bf = -1;
			subLR->bf = 0;
			parent->bf = 0;
		}
		else
		{
			assert(false);
		}
	}

	void RotateRL(Node* parent) {
		Node* subR = parent->right;
		Node* subRL = subR->left;
		int bf = subRL->bf;

		RotateR(parent->right);
		RotateL(parent);

		if (bf == 0)
		{
			subR->bf = 0;
			subRL->bf = 0;
			parent->bf = 0;
		}
		else if (bf == -1)
		{
			subR->bf = 1;
			subRL->bf = 0;
			parent->bf = 0;
		}
		else if (bf == 1)
		{
			subR->bf = 0;
			subRL->bf = 0;
			parent->bf = -1;
		}
		else
		{
			assert(false);
		}
	}

	int _Height(Node* node) {
		if (node == nullptr)
		{
			return 0;
		}
		int LH = _Height(node->left);
		int RH = _Height(node->right);
		return (LH < RH) ? RH + 1 : LH + 1;
	}

	bool _IsBalanceTree(Node* node) {
		if (node == nullptr)
		{
			return true;
		}
		int RTH = _Height(node->right);
		int LTH = _Height(node->left);
		int diff = RTH - LTH;
		if (abs(diff) >= 2)
		{
			cout << node->kv.first << "节点平衡因子异常" << endl;
			return false;
		}
		else if (diff != node->bf) {
			cout << node->kv.first << "节点平衡因子有误" << endl;
		}
		return _IsBalanceTree(node->left) && _IsBalanceTree(node->right);
	}

	void _InOrder(Node* node) {
		if (node == nullptr)
		{
			return;
		}
		_InOrder(node->left);
		cout << node->kv.first << " ";
		_InOrder(node->right);
	}

public:

	int Height() {
		return _Height(root);
	}

	bool IsBalanceTree() {
		return _IsBalanceTree(root);
	}

	void InOrder() {
		_InOrder(root);
		cout << endl;
	}

	bool Insert(const pair<K, V>& kv) {
		if (root == nullptr)
		{
			root = new Node(kv);
			return true;
		}
		Node* cur = root;
		Node* parent = nullptr;
		while (cur)
		{
			if (cur->kv.first < kv.first) {
				parent = cur;
				cur = cur->right;
			}
			else if (cur->kv.first > kv.first)
			{
				parent = cur;
				cur = cur->left;
			}
			else
			{
				return false;
			}
		}
		cur = new Node(kv);
		if (parent->kv.first < cur->kv.first)
		{
			parent->right = cur;
		}
		else if (parent->kv.first > cur->kv.first) {
			parent->left = cur;
		}
		cur->parent = parent;
		while (parent)
		{
			if (cur == parent->left)
			{
				--parent->bf;
			}
			else if (cur == parent->right) {
				++parent->bf;
			}
			if (parent->bf == 0)
			{
				break;
			}
			else if (parent->bf == 1 || parent->bf == -1)
			{
				cur = cur->parent;
				parent = parent->parent;
			}
			else if (parent->bf == 2 || parent->bf == -2) {
				if (parent->bf == 2 && parent->right->bf == 1)
				{
					RotateL(parent);
				}
				else if (parent->bf == -2 && parent->left->bf == -1) {
					RotateR(parent);
				}
				else if (parent->bf == -2 && parent->left->bf == 1)
				{
					RotateLR(parent);
				}
				else if (parent->bf == 2 && parent->right->bf == -1)
				{
					RotateRL(parent);
				}
				break;
			}
			else
			{
				assert(false);
			}
		}
	}
};

void testAVLTree() {
	const int N = 1000;
	vector<int>v;
	srand(time(0));
	for (size_t i = 0; i < N; i++)
	{
		//v.push_back(i);
		v.push_back(rand());
	}
	AVLTress<int, int>avlTree;
	for (auto e : v) {
		avlTree.Insert(make_pair(e, e));
	}

	cout << "是否平衡?" << avlTree.IsBalanceTree() << endl;
	cout << "高度 = " << avlTree.Height() << endl;

	avlTree.InOrder();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值