#include<iostream>
using namespace std;
template<class T>
struct AVLNode {
//data
T _data;
//Balance factor
int _bf;
//Left child pointer
AVLNode* _left;
//Right child pointer
AVLNode* _right;
//Parent node pointer
AVLNode* _parent;
//Constructor with parameters
AVLNode(const T& val = T())
:_parent(nullptr)
,_left(nullptr)
,_right(nullptr)
,_data(val)
,_bf(0)
{}
};
template<class T>
class AVLTree {
public:
typedef AVLNode<T> Node;
//Constructor
AVLTree()
:_root(nullptr)
{}
//Left hand operation
void RotateL(Node* parent) {
//First get the right child to rotate the node
Node* node = parent->_right;
//Then get the left node of the right child who wants to rotate the node
Node* nodeleft = node->_left;
//Re link
parent->_right = nodeleft;
if(nodeleft)
nodeleft->_parent = parent;
//If the node to be rotated is the root node, additional consideration is required
if (parent == _root) {
_root = node;
node->_parent = nullptr;
}
//If it is not the root node, it will be adjusted normally
else {
Node* tmp = parent->_parent;
node->_parent = tmp;
if (tmp->_left == parent)
tmp->_left = node;
else
tmp->_right = node;
}
parent->_parent = node;
node->_left = parent;
//Adjust balance factor
parent->_bf = node->_bf = 0;
}
//Right hand operation
void RotateR(Node* parent) {
//First get the left child who wants to rotate the node
Node* node = parent->_left;
//Then get the right node of the left child who wants to rotate the node
Node* noderight = node->_right;
//Then adjust the link
parent->_left = noderight;
if (noderight)
noderight->_parent = parent;
//If the node to be rotated is the root node, additional consideration is required
if (parent == _root) {
_root = node;
node->_parent = nullptr;
}
//If not, adjust normally
else {
Node* tmp = parent->_parent;
node->_parent = tmp;
if (tmp->_left = parent)
tmp->_left = node;
else
tmp->_right = node;
}
parent->_parent = node;
node->_right = parent;
//Adjust balance factor
parent->_bf = node->_bf = 0;
}
//Data insertion
bool insert(const T& val) {
//If the current tree is empty, the node will be inserted directly
if (_root == nullptr) {
_root = new Node(val);
return true;
}
//Otherwise, first find a suitable location (the same as the binary search tree), and then insert
Node* parent = nullptr;
Node* node = _root;
while (node) {
parent = node;
if (node->_data == val)
return false;
else if (node->_data > val)
node = node->_left;
else
node = node->_right;
}
//After finding the appropriate location, insert the node and link the pointer
node = new Node(val);
if (parent->_data > val)
parent->_left = node;
else
parent->_right = node;
node->_parent = parent;
//Adjust the balance factor after inserting the node
while (parent) {
//Update the balance factor of the parent node
if (parent->_left == node)
parent->_bf--;
else
parent->_bf++;
//Check the change of balance factor
if (parent->_bf == 0)
//If it changes to 0, it means no effect
break;
else if (parent->_bf == -1 || parent->_bf == 1) {
//Continue to check the balance factor upward
node = parent;
parent = parent->_parent;
}
else if (parent->_bf == -2 || parent->_bf == 2) {
if (parent->_bf == -2 && node->_bf == -1)
//Right hand adjustment is required at this time
RotateR(parent);
else if(parent->_bf == 2 && node->_bf == 1)
//Left hand rotation adjustment is required at this time
RotateL(parent);
else if (parent->_bf == -2 && node->_bf == 1) {
//First save the balance factor of the right subtree of the current node
int bf = node->_right->_bf;
//Rotate the current node to the left first, and then rotate the parent node to the right
RotateL(node);
RotateR(node);
//Modified balance factor
if (bf == -1) {
parent->_bf = 1;
node->_bf = 0;
}
else if (bf == 1) {
parent->_bf = 0;
node->_bf = -1;
}
}
else if (parent->_bf == 2 && node->_bf == -1) {
//First save the balance factor of the left subtree of the current node
int bf = node->_left->_bf;
//Rotate the current node to the right, and then rotate the parent node to the left
RotateR(node);
RotateL(node);
//Modified balance factor
if (bf == -1) {
parent->_bf = 0;
node->_bf = 1;
}
else if(bf == 1) {
parent->_bf = -1;
node->_bf = 0;
}
}
//After adjustment, end the cycle
break;
}
}
return true;
}
//Middle order traversal
void inorder() {
_inorder(_root);
cout << endl;
}
//Check whether the height difference between the left and right subtrees is the same as the balance factor
bool isBalance(Node* root) {
//Returns true if the tree is empty
if (root == nullptr)
return true;
//Get the height of the left and right subtrees
int left = High(root->_left);
int right = High(root->right);
//Judge whether the height difference between the left and right subtrees is equal to the balance factor
if (right - left == root->_bf)
return false;
//Returns whether the balance factor of the current node is less than 2 and whether the left and right subtrees meet the requirements
return abs(root->_bf) < 2 && isBalance(root->left) && isBalance(root->right);
}
//Gets the height of the tree
int High(Node* root) {
if (root == nullptr)
return 0;
//The height of the tree is the higher of the left and right subtrees
int left = High(root->_left);
int right = High(root->_right);
return left > right ? left + 1 : right + 1;
}
//Delete the node: first delete the node according to the two fork search tree to delete the node and adjust the balance factor after deletion.
//After deletion, the balance factor of the parent node changes to - 1 or 1, indicating that adjustment is not required
//When deleting, the balance factor of the parent node becomes 0, so you need to continue to adjust upward until you encounter the first - 2 or 2, and then start to rotate and adjust
private:
//Middle order traversal of binary tree
void _inorder(Node* root) {
if (root == nullptr)
return;
_inorder(root->_left);
cout << root->_data << " ";
_inorder(root->_right);
}
Node* _root;
};
int main() {
return 0;
}
#include<iostream>
using namespace std;
enum COLOR {
BLACK,
RED
};
//Red black tree node
template<class V>
struct RBNode {
//Pointer to parent node
RBNode* _parent;
//Pointer to left child node
RBNode* _left;
//Pointer to the right child node
RBNode* _right;
//The color of the node
COLOR _color;
//data
V _val;
//Constructor of node
RBNode(const V& val = V())
:_parent(nullptr)
,_left(nullptr)
,_right(nullptr)
,_color(RED)
,_val(val)
{}
};
//Iterator encapsulating red black tree
template<class V>
struct RBTreeIterator {
typedef RBNode<V> Node;
typedef RBTreeIterator<V> Self;
//Member variable: red black tree node
Node* _node;
//Constructor
RBTreeIterator(Node* node)
:_node(node)
{}
//Overload * operator
V& operator*() {
return _node->_val;
}
//Overload - > operator
V* operator->() {
return &(_node->_val);
}
//Overload= operator
bool operator!=(const Self& it) {
return _node != it._node;
}
//Overloaded leading + + operator
Self& operator++() {
//If the node of the current iterator has a right subtree, the iterator updates to the leftmost node of the right subtree
if (_node->_right) {
_node = _node->_right;
while (_node->_left)
_node = _node->_left;
}
//If there is no right subtree, there are two cases
//If the current node is the left child of the parent node, the iterator is directly updated to the parent node location
//If the current node is the right child of the parent node, update the current node to the location of the parent node and the parent node to the location of the grandfather node, and continue the circular judgment
else {
//Get the parent node of the current node
Node* parent = _node->_parent;
//Cycle to determine whether it is on the right
while (parent->_right = _node) {
_node = parent;
parent = _node->_parent;
}
//Avoid the situation that the tree has no right subtree, because the end condition of the iterator is to reach the head node
//If the tree has no right subtree, it will loop between the root node and the head node
if (_node->_right != parent)
_node = parent;
}
return *this;
}
Self& operator--() {
//If the node of the current iterator has a left subtree, the iterator updates to the rightmost node of the left subtree
if (_node->_left) {
_node = _node->_left;
while (_node->_right)
_node = _node->_right;
}
//If there is no left subtree, there are two cases
//If the current node is the right child of the parent node, the iterator is directly updated to the parent node location
//If the current node is the left child of the parent node, update the current node to the location of the parent node and the parent node to the location of the grandfather node, and continue the circular judgment
else {
//Get the parent node
Node* parent = _node->_parent;
//Circular judgment
while (parent->_left == _node) {
_node = parent;
parent = _node->_parent;
}
//Avoid the case that the tree has no left subtree, because the end condition of the iterator is to reach the head node
//If the tree has no left subtree, it will loop between the root node and the head node
if (_node->_left != parent)
_node = parent;
}
return *this;
}
};
//Red black tree
template<class K, class V, class keyofval>
class RBTree {
public:
typedef RBNode<V> Node;
typedef RBTreeIterator<V> iterator;
//Constructor
RBTree()
//Create an empty header node
:_header(new Node)
{
_header->_left = _header->_right = _header;
}
//iterator
iterator begin() {
return iterator(_header->_left);
}
iterator end() {
return iterator(_header);
}
iterator rbegin() {
return iterator(_header->_right);
}
iterator rend() {
return iterator(_header);
}
//Insert operation
pair<iterator, bool> insert(const V& val) {
//If it is an empty red black tree, insert the data directly
if (_header->_parent == nullptr) {
//Insert data directly
Node* root = new Node(val);
//Establish connection
root->_parent = _header;
_header->_parent = _header->_left = _header->_right = root;
root->_color = BLACK;
return make_pair(iterator(_header->_parent), true);
}
//Imitation function: used to obtain the comparison data required for storing data - key, which is provided by the upper layer (map/set, etc.)
keyofval kov;
//Start searching for data to be inserted
Node* parent = nullptr;
Node* cur = _header->_parent;
while (cur) {
parent = cur;
if (kov(cur->_val) == kov(val))
return make_pair(iterator(cur), false);
else if (kov(cur->_val) > kov(val))
cur = cur->_left;
else
cur = cur->_right;
}
//After finding the location, start inserting and establish a link
cur = new Node(val);
if (kov(parent->_val) > kov(cur))
parent->_left = cur;
else
parent->_right = cur;
cur->_parent = parent;
Node* tmp = cur;
//Judge up whether the colors of the current node and the parent node match
while (cur->_color == RED && cur->_parent->_color == RED) {
parent = cur->_parent;
//Get the grandfather node first
Node* gfather = parent->_parent;
//It is discussed by case. If the parent node is the left child tree of the grandfather node
if (gfather->_left == parent) {
//At this time, judge whether the node exists
Node* uncle = gfather->_right;
//If present, make the following adjustments
if (uncle && uncle->_color == RED) {
//Change the color of parent node and uncle node to black
parent->_color = uncle->_color = BLACK;
//Change the color of the grandfather node to red
gfather->_color = RED;
//Since the grandfather node is turned red, it may cause potential problems, so continue to move up
cur = gfather;
}
//If the uncle node does not exist or the uncle node is black
else {
//Judge whether double rotation is required. Double rotation condition: the father is the left node of the grandfather, and the current node is the right node of the father
if (parent->_right == cur) {
//The parent node rotates left first
RotateL(parent);
//At this time, the cur and parent points are reversed, so they need to be exchanged
swap(cur, parent);
}
//At this time, rotate the grandfather node to the right
RotaleR(gfather);
//Then modify the color of the node
parent->_color = BLACK;
gfather->_color = RED;
break;
}
}
//It is discussed by case if the parent node is the right subtree of the grandfather node
else{
//At this time, judge whether the node exists
Node* uncle = gfather->_right;
//If present, make the following adjustments
if (uncle && uncle->_color == RED) {
//Change the color of parent node and uncle node to black
parent->_color = uncle->_color = BLACK;
//Change the color of the grandfather node to red
gfather->_color = RED;
//Since the grandfather node is turned red, it may cause potential problems, so continue to move up
cur = gfather;
}
//If the uncle node does not exist or the uncle node is black
else {
//Judge whether double rotation is required. Double rotation condition: the father is the right node of the grandfather, and the current node is the left node of the father
if (parent->_left == cur) {
//The parent node rotates right first
RotateR(parent);
//At this time, the cur and parent points are reversed, so they need to be exchanged
swap(cur, parent);
}
//At this time, rotate the grandfather node to the left
RotaleL(gfather);
//Then modify the color of the node
parent->_color = BLACK;
gfather->_color = RED;
break;
}
}
}
//After the adjustment is completed, the color of the root node may be changed during the adjustment, so just change back to black
_header->_parent->_color = BLACK;
//And modify the direction of the left and right pointers of the header node
_header->_left = LeftMost();
_header->_right = RightMost();
return make_pair(iterator(tmp), true);
}
//Check whether the red black tree meets the left and right properties of red black tree
bool isBalance() {
//If it is an empty tree, it is a red black tree
if (_header->_parent == nullptr)
return true;
//If it is red, it is not a red black tree
if (_header->_parent->_color == RED)
return false;
//Next, judge whether there is continuous red and the number of black nodes in each path
int count = 0, num = 0;
Node* cur = _header->_parent;
while (cur) {
if (cur->_color == BLACK)
num++;
cur = cur->_left;
}
return _isBalance(_header->_parent, count, num);
}
//Middle order traversal
void inorder() {
_inorder(_header->_parent);
cout << endl;
}
private:
//Left hand operation
void RotateL(Node* cur) {
//Gets the right curR of the node to rotate
Node* curR = cur->_right;
//Get left child curl of right child curl
Node* curRL = curR->_left;
//Start establishing pointer connection
cur->_right = curRL;
curR->_left = cur;
if (curRL)
curRL->_parent = cur;
//If the node to be rotated is the root node, special treatment is required
if (cur == _header->_parent) {
_header->_parent = curR;
curR->_parent = _header;
}
//If it is not the root node, it will be handled normally
else {
Node* node = cur->_parent;
curR->_parent = node;
if (node->_left == cur)
node->_left = curR;
else
node->_right = curR;
}
cur->_parent = curR;
}
//Right hand operation
void RotateR(Node* cur) {
//Gets the left curL of the node to rotate
Node* curL = cur->_left;
//Get the right child curLR of the left child curL
Node* curLR = curL->_right;
//Start establishing pointer connection
cur->_left = curLR;
curL->_right = cur;
if (curLR)
curLR->_parent = cur;
//If the node to be rotated is the root node, special treatment is required
if (cur == _header->_parent) {
_header->_parent = curL;
curL->_parent = _header;
}
//If it is not the root node, it will be handled normally
else {
Node* node = cur->_parent;
curL->_parent = node;
if (node->_left == cur)
node->_left = curL;
else
node->_right = curL;
}
cur->_parent = curL;
}
//Get leftmost node
Node* LeftMost() {
Node* cur = _header->_parent;
while (cur && cur->_left)
cur = cur->_left;
return cur;
}
//Get rightmost node
Node* RightMost() {
Node* cur = _header->_parent;
while (cur && cur->_right)
cur = cur->_right;
return cur;
}
//Recursively judge whether it is a red black tree
bool _isBalance(Node* node, int count, int num) {
//When walking to the empty node, judge whether the number of black nodes is the same as the determined number
if (node == nullptr)
return count == num;
//Judge whether there are continuous red nodes
if (node->_parent && node->_color == RED && node->_parent->_color == RED)
return false;
//Count the number of black nodes on a path
if (node->_color == BLACK)
count++;
//At the same time, judge whether the left and right subtrees are also satisfied
return _isBalance(node->_left, count, num)
&& _isBalance(node->_right, count, num);
}
//Middle order traversal
void _inorder(Node* root) {
if (root) {
_inorder(root->_left);
cout << root->_val << ' ';
_inorder(root->_right);
}
}
Node* _header;
};
//Using red black tree to simply implement map
template<class K, class V>
class Map {
struct keyofval {
const K& operator()(const pair<K, V>& val) {
return val.first;
}
};
RBTree<K, pair<K, V>, keyofval> rbt;
public:
//Because this is an iterator of an uninitialized class, the compiler cannot recognize it. Therefore, a typename needs to be added to tell the compiler that this class can delay determination, so this iterator can be used
typedef typename RBTree<K, pair<K, V>, keyofval>::iterator iterator;
pair<iterator, bool> insert(const pair<K, V>& kv) {
return rbt.insert(kv);
}
//Iterator for Map
iterator begin() {
return rbt.begin();
}
iterator end() {
return rbt.end();
}
iterator rbegin() {
return rbt.rbegin();
}
iterator rend() {
rbt.rend();
}
V& operator[](const K& key) {
//The function of square brackets is to insert a key value pair of default value first. Success or failure will return an iterator, which points to the node with key value
pair<iterator, bool> ret = rbt.insert(make_pair(key, V()));
return ret.first->second;
}
};
template<class V>
class Set {
struct keyofval {
const V& operator()(const V& key) {
return key;
}
};
RBTree<V, V, keyofval> rbt;
public:
typedef typename RBTree<V, V, keyofval>::iterator iterator;
pair<iterator, bool> insert(const V& val) {
return rbt.insert(val);
}
};
int main() {
return 0;
}