SBTree的左旋右旋以及各种调整操作的基本实现(包含查找第k大的数值)
来源:互联网 发布:百合体验知乎 编辑:程序博客网 时间:2024/05/21 10:56
在完成了左旋和右旋操作之后,我们要实现调用两种单旋操作的逻辑,也就是调整操作。
在插入之后,一共有 44 种触发旋转的情况,分别为 LL 型、LR 型、RR 型和 RL 型。
通过旋转的名称,可以很直观的想到其对应的不平衡的情况——比如 LR 型,就意味着左子树(L)的右子树(R)的元素个数过大。
还记得我们之前讲到过的,SBTree 的平衡条件么?一共有两个:
a: size[right[t]] ≥ max(size[left[left[t]]], size[right[left[t]]])
a:size[right[t]]≥max(size[left[left[t]]],size[right[left[t]]])
b: size[left[t]] ≥ max(size[left[right[t]]], size[right[right[t]]])
b:size[left[t]]≥max(size[left[right[t]]],size[right[right[t]]])
对于 LL 和 LR 型,违反了平衡条件 aa;对于 RR 和 RL 型,则违反了平衡条件 bb。
对应的,LL 型和 LR 型都一定能保证平衡条件 bb 的成立;RR 型和 RL 型也都能一定保证平衡条件 aa 的成立。
我们只需要检查其中一半的情况即可,来避免无谓的判断。我们可以将算法伪代码简化如下:
如果在处理左子树更高的情况:
LL 型:右旋 tt。
LR 型:左旋 tt 的左子树,再右旋 tt。
如果在处理右子树更高的情况:
RR 型:左旋 tt。
RL 型:右旋 tt 的右子树,再左旋 tt。
递归调整左子树其中左子树的左子树更高的情况
递归调整右子树其中右子树的右子树更高的情况
递归调整当前子树其中左子树更高的情况
递归调整当前子树其中右子树更高的情况
为什么可以不考虑右子树其中右子树的左子树更高的情况呢?因为这种情况在第 66 步已经被处理了。左子树其中左子树的右子树更高的情况也类似。因此我们可以通过和之前介绍的相比更简洁、高效的调整算法实现对 SBTree 的维护。
#include <iostream>using namespace std;class SBTNode {public: int data, size, value; SBTNode * lchild, * rchild, * father; SBTNode(int init_data, int init_size = 0, SBTNode * init_father = NULL); ~SBTNode(); void insert(int value); SBTNode * search(int value); SBTNode * predecessor(); SBTNode * successor(); void remove_node(SBTNode * delete_node); bool remove(int value); int select(int k);};class BinaryTree {private: SBTNode * root;public: BinaryTree(); ~BinaryTree(); void insert(int value); bool find(int value); bool remove(int value); int select(int k);};SBTNode ZERO(0);SBTNode * ZPTR = &ZERO;SBTNode::SBTNode(int init_data, int init_size, SBTNode * init_father) { data = init_data; size = init_size; lchild = ZPTR; rchild = ZPTR; father = init_father;}SBTNode::~SBTNode() { if (lchild != ZPTR) { delete lchild; } if (rchild != ZPTR) { delete rchild; }}SBTNode * left_rotate(SBTNode * node) { SBTNode * temp = node->rchild; node->rchild = temp->lchild; temp->lchild->father = node; temp->lchild = node; temp->father = node->father; node->father = temp; temp->size = node->size; node->size = node->lchild->size + node->rchild->size + 1; return temp;}SBTNode * right_rotate(SBTNode * node) { SBTNode * temp = node->lchild; node->lchild = temp->rchild; temp->rchild->father = node; temp->rchild = node; temp->father = node->father; node->father = temp; temp->size = node->size; node->size = node->lchild->size + node->rchild->size + 1; return temp;}SBTNode * maintain(SBTNode * node, bool flag) { if (flag == false) { if (node->lchild->lchild->size > node->rchild->size) { node = right_rotate(node); } else if (node->lchild->rchild->size > node->rchild->size) { node->lchild = left_rotate(node->lchild); node = right_rotate(node); } else { return node; } } else { if (node->rchild->rchild->size > node->lchild->size) { node = left_rotate(node); } else if (node->rchild->lchild->size > node->lchild->size) { node->rchild = right_rotate(node->rchild); node = left_rotate(node); } else { return node; } } node->lchild = maintain(node->lchild, false); node->rchild = maintain(node->rchild, true); node = maintain(node, false); node = maintain(node, true); return node;}SBTNode * insert(SBTNode * node, int value) { if (value == node->data) { return node; } else { node->size++; if (value > node->data) { if (node->rchild == ZPTR) { node->rchild = new SBTNode(value, 1, node); } else { node->rchild = insert(node->rchild, value); } } else { if (node->lchild == ZPTR) { node->lchild = new SBTNode(value, 1, node); } else { node->lchild = insert(node->lchild, value); } } } return maintain(node, value > node->data);}SBTNode * SBTNode::search(int value) { if (data == value) { return this; } else if (value > data) { if (rchild == ZPTR) { return ZPTR; } else { return rchild->search(value); } } else { if (lchild == ZPTR) { return ZPTR; } else { return lchild->search(value); } }}SBTNode * SBTNode::predecessor() { SBTNode * temp = lchild; while (temp != ZPTR && temp->rchild != ZPTR) { temp = temp->rchild; } return temp;}SBTNode * SBTNode::successor() { SBTNode * temp = rchild; while (temp != ZPTR && temp->lchild != ZPTR) { temp = temp->lchild; } return temp;}void SBTNode::remove_node(SBTNode * delete_node) { SBTNode * temp = ZPTR; if (delete_node->lchild != ZPTR) { temp = delete_node->lchild; temp->father = delete_node->father; delete_node->lchild = ZPTR; } if (delete_node->rchild != ZPTR) { temp = delete_node->rchild; temp->father = delete_node->father; delete_node->rchild = ZPTR; } if (delete_node->father->lchild == delete_node) { delete_node->father->lchild = temp; } else { delete_node->father->rchild = temp; } temp = delete_node; while (temp != NULL) { temp->size--; temp = temp->father; } delete delete_node;}bool SBTNode::remove(int value) { SBTNode * delete_node, * current_node; current_node = search(value); if (current_node == ZPTR) { return false; } size--; if (current_node->lchild != ZPTR) { delete_node = current_node->predecessor(); } else if (current_node->rchild != ZPTR) { delete_node = current_node->successor(); } else { delete_node = current_node; } current_node->data = delete_node->data; remove_node(delete_node); return true;}int SBTNode::select(int k) { int rank=lchild->size+1; if(rank==k){ return data; } else if(k<rank){ return lchild->select(k); }else{ return rchild->select(k-rank); }}BinaryTree::BinaryTree() { root = NULL;}BinaryTree::~BinaryTree() { if (root != NULL) { delete root; }}void BinaryTree::insert(int value) { if (root == NULL) { root = new SBTNode(value, 1); } else { root = ::insert(root, value); }}bool BinaryTree::find(int value) { if (root->search(value) == NULL) { return false; } else { return true; }}bool BinaryTree::remove(int value) { return root->remove(value);}int BinaryTree::select(int k) { return root->select(k);}int main() { BinaryTree binarytree; int arr[10] = { 8, 9, 10, 3, 2, 1, 6, 4, 7, 5 }; for (int i = 0; i < 10; i++) { binarytree.insert(arr[i]); } int k; cin >> k; cout << binarytree.select(k) << endl; return 0;}
- SBTree的左旋右旋以及各种调整操作的基本实现(包含查找第k大的数值)
- 序列的左旋右旋
- 字符串的左旋右旋
- 在红黑树的基础上实现区间树的创建,左旋,右旋,插入和查找
- 红黑树的理解与学习&左旋与右旋操作
- c语言----高位舍弃的左旋和右旋操作
- 实现字符串左旋和右旋的常见方法
- 二叉树的左旋和右旋
- AVL树的左旋右旋理解
- 树的左旋与右旋
- 红黑树的插入创建(左旋 右旋)
- 二叉树的左旋和右旋
- 树的左旋与右旋
- 字符串的左旋和右旋
- 树的左旋和右旋
- treap树的操作--查找区间第k大
- C语言:编写一个函数实现一串字符串的左旋或者右旋
- 易的核心理念之天道左旋、地道右旋
- Linux 下源代码阅读工具 —— vim + TagList + CTags
- 风暴项目个性化推荐系统浅析
- shell初期
- C语言学习入门到精通之gcc编译与调试
- Poj 3659 Perfect Service【最小支配集、树型dp】
- SBTree的左旋右旋以及各种调整操作的基本实现(包含查找第k大的数值)
- xp sp3上VS2010后打开cpp 闪烁刷新现象
- 更换服务器IP地址后,Ambari各项服务心跳丢失(heartbeat lost)的解决方案
- Android动画 -- Property Animation(二)
- poj之旅——3259,3268
- error C2275: 'xxx' : illegal use of this type as an expression
- Metamap Java Api 使用教程
- 翻看谷歌源码 那些让人感兴趣的东西--通知的好用功能
- linux基本命令(45)——free命令