PHP红黑源码,红黑树的实现源码(第二次修订版)

/*-----------------------------------------------------------

RB-Tree的插入和删除操作的实现算法

参考资料:

1) <>

2) http://lxr.linux.no/linux/lib/rbtree.c

作者:http://www.cppblog.com/converse/

您可以自由的传播,修改这份代码,转载处请注明原作者

红黑树的几个性质:

1) 每个结点只有红和黑两种颜色

2) 根结点是黑色的

3)空节点是黑色的(红黑树中,根节点的parent以及所有叶节点lchild、rchild都不指向NULL,而是指向一个定义好的空节点)。

4) 如果一个结点是红色的,那么它的左右两个子结点的颜色是黑色的

5) 对于每个结点而言,从这个结点到叶子结点的任何路径上的黑色结点

的数目相同

-------------------------------------------------------------*/

#include

#include

#include

typedef int key_t;

typedef int data_t;

typedef enum color_t

{

RED = 0,

BLACK = 1

}color_t;

typedef struct rb_node_t

{

struct rb_node_t *left, *right, *parent;

key_t key;

data_t data;

color_t color;

}rb_node_t;

/* forward declaration */

rb_node_t* rb_insert(key_t key, data_t data, rb_node_t* root);

rb_node_t* rb_search(key_t key, rb_node_t* root);

rb_node_t* rb_erase(key_t key, rb_node_t* root);

int main()

{

int i, count = 900000;

key_t key;

rb_node_t* root = NULL, *node = NULL;

srand(time(NULL));

for (i = 1; i < count; ++i)

{

key = rand() % count;

if ((root = rb_insert(key, i, root)))

{

printf("[i = %d] insert key %d success!\n", i, key);

}

else

{

printf("[i = %d] insert key %d error!\n", i, key);

exit(-1);

}

if ((node = rb_search(key, root)))

{

printf("[i = %d] search key %d success!\n", i, key);

}

else

{

printf("[i = %d] search key %d error!\n", i, key);

exit(-1);

}

if (!(i % 10))

{

if ((root = rb_erase(key, root)))

{

printf("[i = %d] erase key %d success\n", i, key);

}

else

{

printf("[i = %d] erase key %d error\n", i, key);

}

}

}

return 0;

}

static rb_node_t* rb_new_node(key_t key, data_t data)

{

rb_node_t *node = (rb_node_t*)malloc(sizeof(struct rb_node_t));

if (!node)

{

printf("malloc error!\n");

exit(-1);

}

node->key = key, node->data = data;

return node;

}

/*-----------------------------------------------------------

|   node           right

|   / \    ==>     / \

|   a  right     node  y

|       / \           / \

|       b  y         a   b

-----------------------------------------------------------*/

static rb_node_t* rb_rotate_left(rb_node_t* node, rb_node_t* root)

{

rb_node_t* right = node->right;

if ((node->right = right->left))

{

right->left->parent = node;

}

right->left = node;

if ((right->parent = node->parent))

{

if (node == node->parent->right)

{

node->parent->right = right;

}

else

{

node->parent->left = right;

}

}

else

{

root = right;

}

node->parent = right;

return root;

}

/*-----------------------------------------------------------

|       node           left

|       / \            / \

|    left  y   ==>    a   node

|   / \               / \

|  a   b             b   y

-----------------------------------------------------------*/

static rb_node_t* rb_rotate_right(rb_node_t* node, rb_node_t* root)

{

rb_node_t* left = node->left;

if ((node->left = left->right))

{

left->right->parent = node;

}

left->right = node;

if ((left->parent = node->parent))

{

if (node == node->parent->right)

{

node->parent->right = left;

}

else

{

node->parent->left = left;

}

}

else

{

root = left;

}

node->parent = left;

return root;

}

static rb_node_t* rb_insert_rebalance(rb_node_t *node, rb_node_t *root)

{

rb_node_t *parent, *gparent, *uncle, *tmp;

while ((parent = node->parent) && parent->color == RED)

{

gparent = parent->parent;

if (parent == gparent->left)

{

uncle = gparent->right;

if (uncle && uncle->color == RED)

{

uncle->color = BLACK;

parent->color = BLACK;

gparent->color = RED;

node = gparent;

}

else

{

if (parent->right == node)

{

root = rb_rotate_left(parent, root);

tmp = parent;

parent = node;

node = tmp;

}

parent->color = BLACK;

gparent->color = RED;

root = rb_rotate_right(gparent, root);

}

}

else

{

uncle = gparent->left;

if (uncle && uncle->color == RED)

{

uncle->color = BLACK;

parent->color = BLACK;

gparent->color = RED;

node = gparent;

}

else

{

if (parent->left == node)

{

root = rb_rotate_right(parent, root);

tmp = parent;

parent = node;

node = tmp;

}

parent->color = BLACK;

gparent->color = RED;

root = rb_rotate_left(gparent, root);

}

}

}

root->color = BLACK;

return root;

}

static rb_node_t* rb_erase_rebalance(rb_node_t *node, rb_node_t *parent, rb_node_t *root)

{

rb_node_t *other, *o_left, *o_right;

while ((!node || node->color == BLACK) && node != root)

{

if (parent->left == node)

{

other = parent->right;

if (other->color == RED)

{

other->color = BLACK;

parent->color = RED;

root = rb_rotate_left(parent, root);

other = parent->right;

}

if ((!other->left || other->left->color == BLACK) &&

(!other->right || other->right->color == BLACK))

{

other->color = RED;

node = parent;

parent = node->parent;

}

else

{

if (!other->right || other->right->color == BLACK)

{

if ((o_left = other->left))

{

o_left->color = BLACK;

}

other->color = RED;

root = rb_rotate_right(other, root);

other = parent->right;

}

other->color = parent->color;

parent->color = BLACK;

if (other->right)

{

other->right->color = BLACK;

}

root = rb_rotate_left(parent, root);

node = root;

break;

}

}

else

{

other = parent->left;

if (other->color == RED)

{

other->color = BLACK;

parent->color = RED;

root = rb_rotate_right(parent, root);

other = parent->left;

}

if ((!other->left || other->left->color == BLACK) &&

(!other->right || other->right->color == BLACK))

{

other->color = RED;

node = parent;

parent = node->parent;

}

else

{

if (!other->left || other->left->color == BLACK)

{

if ((o_right = other->right))

{

o_right->color = BLACK;

}

other->color = RED;

root = rb_rotate_left(other, root);

other = parent->left;

}

other->color = parent->color;

parent->color = BLACK;

if (other->left)

{

other->left->color = BLACK;

}

root = rb_rotate_right(parent, root);

node = root;

break;

}

}

}

if (node)

{

node->color = BLACK;

}

return root;

}

static rb_node_t* rb_search_auxiliary(key_t key, rb_node_t* root, rb_node_t** save)

{

rb_node_t *node = root, *parent = NULL;

int ret;

while (node)

{

parent = node;

ret = node->key - key;

if (0 < ret)

{

node = node->left;

}

else if (0 > ret)

{

node = node->right;

}

else

{

return node;

}

}

if (save)

{

*save = parent;

}

return NULL;

}

rb_node_t* rb_insert(key_t key, data_t data, rb_node_t* root)

{

rb_node_t *parent = NULL, *node;

parent = NULL;

if ((node = rb_search_auxiliary(key, root, &parent)))

{

return root;

}

node = rb_new_node(key, data);

node->parent = parent;

node->left = node->right = NULL;

node->color = RED;

if (parent)

{

if (parent->key > key)

{

parent->left = node;

}

else

{

parent->right = node;

}

}

else

{

root = node;

}

return rb_insert_rebalance(node, root);

}

rb_node_t* rb_search(key_t key, rb_node_t* root)

{

return rb_search_auxiliary(key, root, NULL);

}

rb_node_t* rb_erase(key_t key, rb_node_t *root)

{

rb_node_t *child, *parent, *old, *left, *node;

color_t color;

if (!(node = rb_search_auxiliary(key, root, NULL)))

{

printf("key %d is not exist!\n");

return root;

}

old = node;

if (node->left && node->right)

{

node = node->right;

while ((left = node->left) != NULL)

{

node = left;

}

child = node->right;

parent = node->parent;

color = node->color;

if (child)

{

child->parent = parent;

}

if (parent)

{

if (parent->left == node)

{

parent->left = child;

}

else

{

parent->right = child;

}

}

else

{

root = child;

}

if (node->parent == old)

{

parent = node;

}

node->parent = old->parent;

node->color = old->color;

node->right = old->right;

node->left = old->left;

if (old->parent)

{

if (old->parent->left == old)

{

old->parent->left = node;

}

else

{

old->parent->right = node;

}

}

else

{

root = node;

}

old->left->parent = node;

if (old->right)

{

old->right->parent = node;

}

}

else

{

if (!node->left)

{

child = node->right;

}

else if (!node->right)

{

child = node->left;

}

parent = node->parent;

color = node->color;

if (child)

{

child->parent = parent;

}

if (parent)

{

if (parent->left == node)

{

parent->left = child;

}

else

{

parent->right = child;

}

}

else

{

root = child;

}

}

free(old);

if (color == BLACK)

{

root = rb_erase_rebalance(child, parent, root);

}

return root;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/533019.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python 自动点击上传以后上传文件,python使用selenium模拟点击网页实现自动导入上传文件功能...

一、环境准备Python版本&#xff1a;3.4编辑器&#xff1a;Pycharmexcel文件&#xff1a;导入的excel模板二、python代码由于工作需要&#xff0c;需要每天定时导入相关excel文件进入后台数据库&#xff0c;由于导入的逻辑比较复杂&#xff0c;所以决定通过python模拟登陆导入网…

php绘制频谱图,一步一步教你实现iOS音频频谱动画(二)

本文是系列文章中的第二篇&#xff0c;上篇讲述了音频播放和频谱数据计算&#xff0c;本篇讲述数据处理和动画的绘制。前言在上篇文章中我们已经拿到了频谱数据&#xff0c;也知道了数组每个元素表示的是振幅&#xff0c;那这些数组元素之间有什么关系呢&#xff1f;根据FFT的原…

php删除尾部字符,php如何删除字符串末尾字符

我们知道字符串删除字符的方式有好几种&#xff0c;今天就来介绍三种php删除字符串最后一个字符的函数&#xff0c;有需要的小伙伴可以参考一下。方法一&#xff1a;substr()函数substr()函数返回字符串的一部分。语法如下&#xff1a;substr(string string, int start, int [l…

empinfo Oracle数据库,Oracle数据库---包

--根据员工号或员工姓名获取员工的信息--根据员工号或员工姓名删除员工的信息--创建包规范CREATE OR REPLACE PACKAGE overload_pkgISFUNCTION get_info(eno NUMBER) RETURN emp%ROWTYPE;FUNCTION get_info(name VARCHAR2) RETURN emp%ROWTYPE;PROCEDURE del_emp(eno NUMBER);P…

oracle查看context,oracle context(上下文)

context在计算机领域翻译为上下文context的信息也就是当前会话中的环境变量&#xff0c;如&#xff1a;登录的session_id&#xff0c;用户名&#xff0c;语言等信息查看context中的属性信息。oracle默认的为我们创建了一个context叫userenv(user environment)SYS_CONTEXT(USERE…

oracle标量子查询的优势,标量子查询

--标量子查询select e.empno, e.ename, e.sal, e.deptno,(select d.dname from dept d where e.deptno d.deptno)as dnamefrom emp e--插入一条数据insert into emp(empno,deptno) values(9999,null)--返回结果15条记录--改成left join(hash outer)select e.empno, e.ename, e…

切割照片php上传,php下ajax的文件切割上传

var myForm document.getElementById("myForm");var upfile document.getElementById("upfile");myForm.onsubmit function() {//获取文件对象var file upfile.files[0];//获取文件大小var fileSize file.size;//一次截取的大小(字节)var CutSize 10…

oracle插补缺失日期,Oracle连接 ORA-28001: 口令已经失效解决方法

cmd进入命令行C:UsersAdministrator>sqlplus / as sysdbaSQL*Plus: Release 11.2.0.1.0 Production on 星期四 9月 24 15:19:21 2020Copyright (c) 1982, 2010, Oracle. All rights reserved.连接到:Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Pr…

PHP 蒙太奇马赛克拼图,AndreaMosaic制作一幅马赛克拼图

大家在网上应该都见过用很多幅图片拼成的马赛克图片&#xff0c;今天小编就为大家介绍AndreaMosaic制作一幅马赛克拼图方法&#xff0c;不会的朋友快快来学习吧&#xff01;软件名称&#xff1a;AndreaMosaic(蒙太奇图片制作软件) V6.1.0.4 中文安装免费版软件大小&#xff1a;…

php mongo 查询count,[PHP] 使用PHP在mongodb中进行count查询

原文&#xff1a;https://www.cnblogs.com/taoshihan/p/12362111.html在php7的mongodb扩展中&#xff0c;当要查询某个集合在某个条件下的数据个数时&#xff0c;可以使用下面的方式来获取。比原生的命令要复杂许多比旧版mongo扩展也复杂许多需要使用到MongoDB\Driver\Command …

oracle字段类型设计,Oracle字段类型设计与实际业务不符引发的问题

在Oracle表的设计过程中&#xff0c;开发人员总是对字段的类型不以为然&#xff0c;下面来演示一个例子&#xff0c;按照应该设计为number的&#xff0c;结果设计成了varcha在Oracle表的设计过程中&#xff0c;开发人员总是对字段的类型不以为然&#xff0c;下面来演示一个例子…

linux下进程监控6,Linux进程监控技术—精通软件性能测试与LoadRunner最佳实战(6)...

8.2.5 Linux操作系统进程监控技术Linux在进程监控方面同样出色&#xff0c;不仅可以通过图形用户界面的管理工具&#xff0c;还可以用命令方式显示进程相关信息。像“Windows的任务管理器”一样&#xff0c;在RedHat 9中可以通过单击“系统工具”→“系统监视器”&#xff0c;…

linux pcie命令,setpci命令_Linux setpci 命令用法详解:查询和配置PCI设备的使用工具...

setpci命令是一个查询和配置PCI设备的使用工具。语法setpci(选项)(参数)选项-v&#xff1a;显示指令执行的细节信息&#xff1b;-f&#xff1a;当没有任何操作需要完成时&#xff0c;不显示任何信息&#xff1b;-D&#xff1a;测试模式&#xff0c;并不真正将配置信息写入寄存器…

linux proc文件 write的原子性,Linux命令之write调用的原子性

linux命令是对Linux系统进行管理的命令。本文介绍的关于linux命令中write调用的原子性的详细描述&#xff0c;具体内容如下所述。UNIX环境高级编程中关于原子操作的介绍&#xff0c;其中有一种情形是在文件尾端添加数据。文中说&#xff0c;如果多个进程都需要将数据添加到某一…

linux 命令行 迅雷替代,Mac/Linux下迅雷替代方案

还记得我两年前写的《DIY了家用NAS》吗&#xff1f;现在又带来新的升级啦。当初的NAS最多能使用Transmission来进行BT下载&#xff0c;那时就在想&#xff0c;如果能下载普通的http资源就好了。再进一步&#xff0c;有什么方案可以通吃所有下载方式呢&#xff1f; 记得那个时候…

linux好用的编译器,推荐几款Linux下比Notepad++好的编辑器软件

Notepad这一段又出风头了&#xff0c;好好的做你软件多好&#xff0c;非得参杂入政治。前两天开源文本编辑器 Notepad 发布了 7.8.1 版本&#xff0c;然后在该版本中作者居然摸黑中国&#xff0c;具体的内容请大家自行百度。而且这已经不是 Notepad 第一次这么干了&#xff01;…

linux下调用python脚本,Linux下QT调用Python脚本的解决方案,Qt,python,一种,解决办法

最近在做一个深度学习对图片中对象识别效果的检测工具&#xff0c;其主要功能就是将自己标注的图片与识别结果图片进行对比然后计算识别的准确等参数&#xff0c;并提供原图与结果图片的显示功能。脚本主要完成识别与计算功能&#xff0c;QT完成数据的整理显示与图片的显示。我…

linux获取bind返回值信息,v$sql_bind_capture 获取绑定变量信息

截取自v$sql_bind_capture 对于游标中定义的每一个绑定变量都会有视图中的一行对应。主要包含三个部分&#xff1a;指向父游标(hash_value, address)和子游标(hash_value, child_address)的信息,变量类型定义&#xff0c;变量的值(不包含复杂的值&#xff1a;LONG,LOB,和…

linux boost教程,Linux上安装使用Boost入门指导

获得boostboost分布只需要头文件的库使用boost建立一个简单的程序准备使用boost二进制文件库把你的程序链接到boost库1.获得boost解压2.boost分布boost_1_46_1.........................boost根目录boost/.....................................所有boost头文件libs/..........…

vps如何linux内核4.19,Linux kernel 4.19 RC1 发布,一个相当大的版本

原标题&#xff1a;Linux kernel 4.19 RC1 发布&#xff0c;一个相当大的版本Linus Torvalds今天发布了第一个候选版本(RC)&#xff0c;正式启动了即将推出的Linux 4.19内核系列的开发周期。自Linux 4.18内核系列推出以来已经过去两周了&#xff0c;因此下一个主要版本Linux ke…