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.pswp.cn/news/533019.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/533019.shtml
英文地址,請注明出處:http://en.pswp.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…