#include <iostream>
#include <algorithm>
#include <vector>
#include <stdlib.h>
#include <time.h>
typedef struct node{
public:
int key;
int priority;
int size;
node *left;
node *right;
node *parent;
node(int k);
} node;
node::node(int k){
key = k;
priority = rand() % 701;
size = 1;
left = right = parent = NULL;
}
/*Возвращает указатель на узел, содержащий i-й в порядке
*возрастания ключ в поддереве с корнем root*/
struct node * os_select(struct node *root, int i){
int r;
if (root != NULL && root->left)
r = root->left->size + 1;
else
r = 1;
if(i == r) return root;
else{
if(i < r) return os_select(root->left, i);
else return os_select(root->right, i - r);
}
}
/*По заданному указателю на узел x дерева с корнем root
*возвращает позицию данного узла при центрированном обходе*/
int os_rank(struct node *root, struct node *x){
int r = x->left->size + 1;
struct node *y = x;
while(y != root){
if(y == y->parent->right)
r = r + y->parent->left->size + 1;
y = y->parent;
}
return r;
}
void traversal(node *root, int level) {
if (root != NULL) {
traversal(root->left, level+1);
for (int i =0; i< level; ++i)
printf("--");
printf("%d %d %d\n", root->key, root->priority, root->size);
traversal(root->right, level+1);
}
}
void left_rotate(node **root, node *x) { // NOTE: node **root
node *y = x->right;
x->right = y->left;
if (y->left != NULL) y->left->parent = x;
y->parent = x->parent;
if (x->parent == NULL) *root = y; // NOTE: корень может помен¤тьс¤!
else {
if (x == x->parent->left) x->parent->left = y;
else x->parent->right = y;
}
y->left = x;
x->parent = y;
// Пересчет полей size после поворота
y->size = x->size;
x->size = 1;
if (x->left)
x->size += x->left->size;
if (x->right)
x->size += x->right->size;
}
void right_rotate(node **root, node *x) { // NOTE: node **root
node *y = x->left;
x->left = y->right;
if (y->right != NULL) y->right->parent = x;
y->parent = x->parent;
if (x->parent == NULL) *root = y; // NOTE: корень может поменяться!
else {
if (x == x->parent->right) x->parent->right = y;
else x->parent->left = y;
}
y->right = x;
x->parent = y;
// Пересчет полей size после поворота
y->size = x->size;
x->size = 1;
if (x->left)
x->size += x->left->size;
if (x->right)
x->size += x->right->size;
}
void insert(node **root, node *z) { // NOTE: node **root
node *x = *root; //отмечает проходимый путь
node *y = NULL; //ссылается на родительский по отношению к x узел
node *p = NULL;
while (x != NULL) {
y = x;
if (z->key < x->key) x = x->left;
else x = x->right;
}
z->parent = y;
if (y == NULL) *root = z; // NOTE: корень может поменяться!
else {
if (z->key < y->key) y->left = z;
else y->right = z;
}
z->size = 1;
x = z; //Для прохода вверх
while (x != *root && x->priority > x->parent->priority) {
if (x == x->parent->left)
right_rotate(root, x->parent);
else /* x == x->parent->right */
left_rotate(root, x->parent);
}
}
int main(){
std::vector<int> v;
srand(time(NULL));
/*for(int i = 0; i < 50000; i++)
v.push_back(i);
std::random_shuffle(v.begin(), v.end());
std::nth_element(v.begin(), v.begin() + 5, v.end());
std::cout << "the n-th: " << v[5] << std::endl;*/
node *tree = NULL, *p, *nth;
for(int i = 0; i < 10; i++){
p = new node(i*11 % 17);
insert(&tree, p);
}
traversal(tree,0);
nth = os_select(tree, 10);
std::cout << "nth element:" << std::endl;
std::cout << nth->key << std::endl;
int pause = 0;
std::cin >> pause;
}