递归检索元素os_select
node* os_select(tree &t, int i) //返回第i小的结点,递归
{
node *x = t;
int r = x->left->size + 1;
if (i == r)
return x;
else if (i < r)
return os_select(x->left, i);
else
return os_select(x->right, i - r);
}
迭代检索元素os_select
node* os_select_(tree &t, int i) //diedai
{
node *x = t;
int r = x->left->size + 1;
while (i != r)
{
r = x->left->size + 1;
if (i < r)
{
x = x->left;
}
else if(i>r)
{
x = x->right;
i = i - r;
}
}
return x;
}
递归检索秩os_rank
int os_rank_(node*x,tree &t, int m) //digui
{
static int r = x->left->size + 1;
node *y = x;
if (y==t)
return r;
else
{
if (y == y->parent->right)
r = r + y->parent->left->size + 1;
return os_rank_(y->parent,t, m);
}
}
迭代检索秩os_rank
int os_rank(tree &t, int m) //返回元素值为x的次序
{
node* x=search(t, m);
int r = x->left->size + 1;
node *y = x;
while (y != nil)
{
if (y == y->parent->right)
r = r + y->parent->left->size + 1;
y = y->parent;
}
return r;
}
完整代码
从红黑树代码修改而来,主要是加入size,以及在insert和delete和left_rotate、right_rotate时去修改size变化
#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
typedef int type;
typedef enum Color //定义红黑树结点颜色颜色类型
{
red = 0,
black = 1
}Color;
typedef struct rbtree //定义红黑树的结构
{
Color color;
type key;
type size;
struct rbtree *left;
struct rbtree *right;
struct rbtree *parent;
}node, *tree;
node *nil = NULL; //创建一个哨兵结点。这里要用哨兵去让空的叶子结点的颜色是black的,参照红黑树的定义
node* create(type key, node *left, node *right, node *parent,type size) //创建结点
{
node *p;
node *nil;
nil = (node*)malloc(sizeof(node));
p = (node*)malloc(sizeof(node));
nil->parent = NULL;
nil->left = NULL;
nil->color = black;
nil->key = NULL;
nil->size = 0;
p->color = black; //默认颜色为black
p->left = left;
p->right = right;
p->parent = parent;
p->key = key;
p->size = size;
/* printf("创造结点完毕");*/
return p;
}
void left_rotate(tree &t, node *x) //左旋,这个看图就能理解具体操作
{
if (x->right != nil)
{
node *y = x->right;
x->right = y->left;
if (y->left != nil)
y->left->parent = x;
y->parent = x->parent;
if (x->parent == nil)
t = y;
else
{
if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
}
y->left = x;
x->parent = y;
y->size = x->size;
x->size = x->left->size + x->right->size + 1;
}
else
{
printf("%s/n", "can't execute left rotate due to null right child");
}
}
void right_rotate(tree &t, node *x) //右旋
{
if (x->left != nil)
{
node *y = x->left;
x->left = y->right;
if (y->right != nil)
y->right->parent = x;
y->parent = x->parent;
if (x->parent == nil)
t = y; //
else
{
if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
}
y->right = x;
x->parent = y;
y->size = x->size;
x->size = x->left->size + x->right->size + 1;
}
else
printf("%s/n", "can't execute right rotate due to null left child");
}
node* search(tree &t, type key) //查找元素
{
node *x = t;
if (x == nil || x->key == key)
{
return t;
}
if (key < x->key)
{
return search(x->left, key);
}
else
{
return search(x->right, key);
}
} //递归查找
node* os_select(tree &t, int i) //返回第i小的结点,递归
{
node *x = t;
int r = x->left->size + 1;
if (i == r)
return x;
else if (i < r)
return os_select(x->left, i);
else
return os_select(x->right, i - r);
}
node* os_select_(tree &t, int i) //diedai
{
node *x = t;
int r = x->left->size + 1;
while (i != r)
{
r = x->left->size + 1;
if (i < r)
{
x = x->left;
}
else if(i>r)
{
x = x->right;
i = i - r;
}
}
return x;
}
int os_rank(tree &t, int m) //返回元素值为x的次序
{
node* x=search(t, m);
int r = x->left->size + 1;
node *y = x;
while (y != nil)
{
if (y == y->parent->right)
r = r + y->parent->left->size + 1;
y = y->parent;
}
return r;
}
int os_rank_(node*x,tree &t, int m) //digui
{
static int r = x->left->size + 1;
node *y = x;
if (y==t)
return r;
else
{
if (y == y->parent->right)
r = r + y->parent->left->size + 1;
return os_rank_(y->parent,t, m);
}
}
void rb_insert_fixup(tree &t, node* z)
{
node *y;
while ((z->parent != nil) && (z->parent->color == red)) //only when z's parent is red there will probably obey the red node has two black nodes
{
if (z->parent == z->parent->parent->left) //z'parent is the left node
{
y = z->parent->parent->right; //let y be z's uncle node
if (y->color == red) //parent and uncle and itself are all red
{
z->parent->color = black;
y->color = black;
z->parent->parent->color = red;
z = z->parent->parent; //let z up to its grandpa
}
else
{
if (z == z->parent->right) // z is a right node
{
z = z->parent;
left_rotate(t, z);
}
z->parent->color = black;
z->parent->parent->color = red;
right_rotate(t, z->parent->parent);
}
}
else //z's parent is the right node
{
y = z->parent->parent->left;
if (y->color == red)
{
z->parent->color = black;
y->color = black;
z->parent->parent->color = red;
z = z->parent->parent;
}
else
{
if (z == z->parent->left) // z is a left node
{
z = z->parent;
right_rotate(t, z);
}
z->parent->color = black;
z->parent->parent->color = red;
left_rotate(t, z->parent->parent);
}
}
}
t->color = black; //始终保持根节点是黑色
}
node* rb_insert(tree &t, node *z) //插入操作
{
if (t == NULL) //t是空的树
{
t = (tree)malloc(sizeof(node));
nil = (node*)malloc(sizeof(node)); //初始化哨兵结点
nil->color = black;
nil->size = 0;
t->left = nil;
t->right = nil;
t->parent = nil;
t->key = z->key;
t->size = 1;
t->color = black;
}
else
{
node *y = nil;
node *x = t; //
while (x != nil)
{
y = x;
x->size++;
if (z->key < x->key)
x = x->left;
else
x = x->right;
}
z->parent = y;
if (y == nil)
t = z;
else
{
if (z->key < y->key)
y->left = z;
else
y->right = z;
}
z->left = nil;
z->right = nil;
z->color = red;
z->size = 1;
//始终保持插入的结点是红色,不符合具体性质了再用fixup调整
rb_insert_fixup(t, z);
}
return t;
}
node* rb_insert_(tree &t, type k)
{
node *z;
z = create(k, nil, nil, nil,1);
return rb_insert(t, z);
}
node* min(tree &m) //最小值
{
node *n = m;
if (n == nil)
return nil;
while (n->left != nil)
{
n = n->left;
}
return n;
}
node* successor(node *s) //后继
{
node *p;
node *m = s; //代替s去移动
if (m->right != nil) //结点右子树非空
{
return min(m->right);
}
else
{
p = m->parent; //结点是左孩子,后继就是他的父节点
while (p != nil && p->right == m)
{ //结点是右孩子,向上查找,直到遇到一个有左孩子的父节点,那就是后继
{
m = p;
p = p->parent;
}
}
return p;
}
}
void rb_delete_fixup(tree &t, node *x)
{
node *w;
while (x != t && x->color == black) //
{
if (x == x->parent->left)
{
w = x->parent->right;
if (w->color == red)
{
w->color = black;
x->parent->color = red;
left_rotate(t, x->parent);
w = x->parent->right;
}
if (w->left->color == black && w->right->color == black)
{
w->color = red;
x = x->parent;
}
else if (w->right->color == black)
{
w->left->color = black;
w->color = red;
right_rotate(t, w);
w = x->parent->right;
}
w->color = x->parent->color;
x->parent->color = black;
w->right->color = black;
left_rotate(t, x->parent);
x = t; //
}
else
{
w = x->parent->left;
if (w->color = red)
{
w->color = black;
x->parent->color = red;
right_rotate(t, x->parent);
w = x->parent->left;
}
if (w->left->color == black && w->right->color == black)
{
w->color = red;
x = x->parent;
}
else if (w->left->color == black)
{
w->right->color = black;
w->color = red;
left_rotate(t, w);
w = x->parent->right;
}
w->color = x->parent->color;
x->parent->color = black;
w->left->color = black;
right_rotate(t, x->parent);
x = t; //
}
}
x->color = black;
}
node* rb_delete(tree &t, node *z)
{
node *y, *x;
node *m = nil;
node* n = z;
node *xxx = z->parent;
if (z->left == nil || z->right == nil)
{
while (xxx != nil)
{
xxx->size--;
xxx=xxx->parent;
}
y = z;
}
else
{
y = successor(n);
xxx = y->parent;
while (xxx != nil)
{
xxx->size--;
xxx = xxx->parent;
}
//这一行使z的右孩子发生变化
}
if (y->left != nil)
x = y->left;
else
x = y->right;
x->parent = y->parent;
if (y->parent == nil)
t = x; //
else
{
if (y == y->parent->left)
y->parent->left = x;
else
y->parent->right = x;
}
if (y != z)
{
z->key = (y->key);
}
if (y->color == black)
rb_delete_fixup(t, x);
return t;
}
node* rb_delete_(tree &t, type k)
{
node *z;
z = search(t, k);
if (z != nil)
{
t = rb_delete(t, z);
}
else
printf("无此元素");
return t;
}
void print_tree(tree &t) //中序遍历打印
{
if (t != nil && t != NULL)
{
print_tree(t->left);
printf("%7d , %5d\n, size= %5d\n ", t->key, t->color,t->size);
print_tree(t->right);
}
}
int main()
{
int i;
tree zz = NULL, mm = NULL, nn = NULL, xx = NULL, yy = NULL;
type k;
int a[12] = { 3,12,15,17,19,55,20,18,36,48,31,29 };
printf("\n原来的数字是:----------------------------------------\n");
for (i = 0; i<12; i++)
{
printf("%d ", a[i]);
zz = rb_insert_(zz, a[i]);
}
printf("\n中序遍历是:-------------------------------------------\n");
printf("规定:red=0,black=1\n");
print_tree(zz);
printf("要查询第几小的元素:------------------------------------\n");
scanf_s("%d", &k);
printf("%d\n",os_select_(zz, k)->key);
printf("要查询哪个元素的秩:-----------------------------------\n");
scanf_s("%d", &k);
printf("%d\n", os_rank_(search(zz,k),zz, k)); //递归
printf("\n要删除的值是:---------------------------------------");
scanf_s("%d", &k);
yy = rb_delete_(zz, k);
print_tree(yy);
printf("\n要插入的值是:--------------------------------------");
scanf_s("%d", &k);
rb_insert_(zz, k);
print_tree(zz);
}