C++實(shí)現(xiàn)紅黑樹(shù)應(yīng)用實(shí)例代碼
紅黑樹(shù)的應(yīng)用:
1、利用key_value對(duì),快速查找,O(logn)
- socket與客戶端id之間,形成映射關(guān)系(socket, id)
- 內(nèi)存分配管理
- 一整塊內(nèi)存,不斷分配小塊
- 每分配一次,就加入到紅黑樹(shù)
- 釋放的時(shí)候,在紅黑樹(shù)找到相應(yīng)的塊,然后去釋放
2、利用紅黑樹(shù)中序遍歷是順序的特性
- 進(jìn)程的調(diào)度
- 進(jìn)程處于等待狀態(tài),每個(gè)進(jìn)程都有等待的時(shí)間,在未來(lái)某個(gè)時(shí)刻會(huì)運(yùn)行,將這些進(jìn)程利用紅黑樹(shù)組織起來(lái)
- 在某個(gè)時(shí)刻,找到對(duì)應(yīng)時(shí)刻的節(jié)點(diǎn),然后中序遍歷,就可以把該節(jié)點(diǎn)之前的節(jié)點(diǎn)全部運(yùn)行到。
3、nginx定時(shí)器
為什么使用紅黑樹(shù)不使用哈希表?
- 極少情況下,需要key是有序的,如定時(shí)器
二叉排序樹(shù)(bstree)
- 左子樹(shù) < 根 < 右子樹(shù)
- 中序遍歷結(jié)果是順序的
- 極端情況下,如果順序插入,結(jié)果就成了鏈表
- 為了解決這個(gè)問(wèn)題,引入了紅黑樹(shù)
- 為了解決這個(gè)問(wèn)題,引入了紅黑樹(shù)
紅黑樹(shù)性質(zhì)
- 每個(gè)節(jié)點(diǎn)是紅色的或黑色的
- 根節(jié)點(diǎn)是黑色的
- 葉子節(jié)點(diǎn)是黑色的
- 紅色節(jié)點(diǎn)的兩個(gè)子節(jié)點(diǎn)必須是黑色的
- 對(duì)每個(gè)節(jié)點(diǎn),該節(jié)點(diǎn)到其子孫節(jié)點(diǎn)的所有路徑上的包含相同數(shù)目的黑節(jié)點(diǎn)(黑高相同)
- 最短路徑就是全黑
- 最長(zhǎng)路徑就是黑紅相間
如何證明紅黑樹(shù)的正確性?
- 采用歸納法
左旋與右旋
- 改變?nèi)齻€(gè)方向,六根指針
紅黑樹(shù)的插入:
- 插入節(jié)點(diǎn)的時(shí)候,原先的樹(shù)是滿足紅黑樹(shù)性質(zhì)的
- 插入節(jié)點(diǎn)的顏色是紅色更容易滿足紅黑樹(shù)的性質(zhì)
- 插入的節(jié)點(diǎn)是紅色,且其父節(jié)點(diǎn)也是紅色的時(shí)候,需要調(diào)整
插入有三種情況:
- 叔父節(jié)點(diǎn)是紅色
- 叔父節(jié)點(diǎn)是黑色,且祖父節(jié)點(diǎn),父節(jié)點(diǎn)和插入節(jié)點(diǎn)不是一條直線
- 叔父節(jié)點(diǎn)是黑色,且祖父節(jié)點(diǎn),父節(jié)點(diǎn)和插入節(jié)點(diǎn)是一條直線
平衡二叉樹(shù):
- 內(nèi)部不是color,而是一個(gè)high記錄高度,如果左右子樹(shù)高度相差超過(guò)1,就需要調(diào)整。
紅黑樹(shù)的刪除:
- 什么是刪除節(jié)點(diǎn)? y-> y是z的后繼節(jié)點(diǎn)
- 什么是軸心節(jié)點(diǎn)? x是y的右子樹(shù)
- 如果x是紅色,把x變成黑色
- 如果x是黑色,需要進(jìn)行調(diào)整
刪除y節(jié)點(diǎn),是什么顏色的時(shí)候需要調(diào)整?
- 黑色需要調(diào)整,刪除黑色破壞了黑高
#include <stdio.h> #include <stdlib.h> #include <string.h> #define RED 1 #define BLACK 2 typedef int KEY_TYPE; typedef struct _rbtree_node { unsigned char color; struct _rbtree_node *right; struct _rbtree_node *left; struct _rbtree_node *parent; KEY_TYPE key; void *value; } rbtree_node; typedef struct _rbtree { rbtree_node *root; rbtree_node *nil; } rbtree; rbtree_node *rbtree_mini(rbtree *T, rbtree_node *x) { while (x->left != T->nil) { x = x->left; } return x; } rbtree_node *rbtree_maxi(rbtree *T, rbtree_node *x) { while (x->right != T->nil) { x = x->right; } return x; } rbtree_node *rbtree_successor(rbtree *T, rbtree_node *x) { rbtree_node *y = x->parent; if (x->right != T->nil) { return rbtree_mini(T, x->right); } while ((y != T->nil) && (x == y->right)) { x = y; y = y->parent; } return y; } void rbtree_left_rotate(rbtree *T, rbtree_node *x) { rbtree_node *y = x->right; // x --> y , y --> x, right --> left, left --> right x->right = y->left; //1 1 if (y->left != T->nil) { //1 2 y->left->parent = x; } y->parent = x->parent; //1 3 if (x->parent == T->nil) { //1 4 T->root = y; } else if (x == x->parent->left) { x->parent->left = y; } else { x->parent->right = y; } y->left = x; //1 5 x->parent = y; //1 6 } void rbtree_right_rotate(rbtree *T, rbtree_node *y) { rbtree_node *x = y->left; y->left = x->right; if (x->right != T->nil) { x->right->parent = y; } x->parent = y->parent; if (y->parent == T->nil) { T->root = x; } else if (y == y->parent->right) { y->parent->right = x; } else { y->parent->left = x; } x->right = y; y->parent = x; } void rbtree_insert_fixup(rbtree *T, rbtree_node *z) { while (z->parent->color == RED) { //z ---> RED if (z->parent == z->parent->parent->left) { rbtree_node *y = z->parent->parent->right; if (y->color == RED) { z->parent->color = BLACK; y->color = BLACK; z->parent->parent->color = RED; z = z->parent->parent; //z --> RED } else { if (z == z->parent->right) { z = z->parent; rbtree_left_rotate(T, z); } z->parent->color = BLACK; z->parent->parent->color = RED; rbtree_right_rotate(T, z->parent->parent); } }else { rbtree_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; //z --> RED } else { if (z == z->parent->left) { z = z->parent; rbtree_right_rotate(T, z); } z->parent->color = BLACK; z->parent->parent->color = RED; rbtree_left_rotate(T, z->parent->parent); } } } T->root->color = BLACK; } void rbtree_insert(rbtree *T, rbtree_node *z) { rbtree_node *y = T->nil; rbtree_node *x = T->root; while (x != T->nil) { y = x; if (z->key < x->key) { x = x->left; } else if (z->key > x->key) { x = x->right; } else { //Exist return ; } } z->parent = y; if (y == T->nil) { T->root = z; } else if (z->key < y->key) { y->left = z; } else { y->right = z; } z->left = T->nil; z->right = T->nil; z->color = RED; rbtree_insert_fixup(T, z); } void rbtree_delete_fixup(rbtree *T, rbtree_node *x) { while ((x != T->root) && (x->color == BLACK)) { if (x == x->parent->left) { rbtree_node *w= x->parent->right; if (w->color == RED) { w->color = BLACK; x->parent->color = RED; rbtree_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; rbtree_right_rotate(T, w); w = x->parent->right; } w->color = x->parent->color; x->parent->color = BLACK; w->right->color = BLACK; rbtree_left_rotate(T, x->parent); x = T->root; } } else { rbtree_node *w = x->parent->left; if (w->color == RED) { w->color = BLACK; x->parent->color = RED; rbtree_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; rbtree_left_rotate(T, w); w = x->parent->left; } w->color = x->parent->color; x->parent->color = BLACK; w->left->color = BLACK; rbtree_right_rotate(T, x->parent); x = T->root; } } } x->color = BLACK; } rbtree_node *rbtree_delete(rbtree *T, rbtree_node *z) { rbtree_node *y = T->nil; rbtree_node *x = T->nil; if ((z->left == T->nil) || (z->right == T->nil)) { y = z; } else { y = rbtree_successor(T, z); } if (y->left != T->nil) { x = y->left; } else if (y->right != T->nil) { x = y->right; } x->parent = y->parent; if (y->parent == T->nil) { T->root = x; } else if (y == y->parent->left) { y->parent->left = x; } else { y->parent->right = x; } if (y != z) { z->key = y->key; z->value = y->value; } if (y->color == BLACK) { rbtree_delete_fixup(T, x); } return y; } rbtree_node *rbtree_search(rbtree *T, KEY_TYPE key) { rbtree_node *node = T->root; while (node != T->nil) { if (key < node->key) { node = node->left; } else if (key > node->key) { node = node->right; } else { return node; } } return T->nil; } void rbtree_traversal(rbtree *T, rbtree_node *node) { if (node != T->nil) { rbtree_traversal(T, node->left); printf("key:%d, color:%d\n", node->key, node->color); rbtree_traversal(T, node->right); } } int main() { int keyArray[20] = {24,25,13,35,23, 26,67,47,38,98, 20,19,17,49,12, 21,9,18,14,15}; rbtree *T = (rbtree *)malloc(sizeof(rbtree)); if (T == NULL) { printf("malloc failed\n"); return -1; } T->nil = (rbtree_node*)malloc(sizeof(rbtree_node)); T->nil->color = BLACK; T->root = T->nil; rbtree_node *node = T->nil; int i = 0; for (i = 0;i < 20;i ++) { node = (rbtree_node*)malloc(sizeof(rbtree_node)); node->key = keyArray[i]; node->value = NULL; rbtree_insert(T, node); } rbtree_traversal(T, T->root); printf("----------------------------------------\n"); for (i = 0;i < 20;i ++) { rbtree_node *node = rbtree_search(T, keyArray[i]); rbtree_node *cur = rbtree_delete(T, node); free(cur); rbtree_traversal(T, T->root); printf("----------------------------------------\n"); } }
總結(jié)
到此這篇關(guān)于C++實(shí)現(xiàn)紅黑樹(shù)的文章就介紹到這了,更多相關(guān)C++實(shí)現(xiàn)紅黑樹(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- C++詳細(xì)實(shí)現(xiàn)紅黑樹(shù)流程詳解
- C++?STL容器詳解之紅黑樹(shù)部分模擬實(shí)現(xiàn)
- C++數(shù)據(jù)結(jié)構(gòu)之紅黑樹(shù)的實(shí)現(xiàn)
- C++超詳細(xì)分析紅黑樹(shù)
- C++數(shù)據(jù)結(jié)構(gòu)紅黑樹(shù)全面分析
- C++?RBTree紅黑樹(shù)的性質(zhì)與實(shí)現(xiàn)
- C++使用一棵紅黑樹(shù)同時(shí)封裝出map和set實(shí)例代碼
- C++紅黑樹(shù)應(yīng)用之手搓set和map
- C++實(shí)現(xiàn)紅黑樹(shù)核心插入實(shí)例代碼
相關(guān)文章
C語(yǔ)言中字符串和數(shù)字的相互轉(zhuǎn)換實(shí)現(xiàn)代碼
以下是對(duì)C語(yǔ)言中字符串和數(shù)字的相互轉(zhuǎn)換實(shí)現(xiàn)代碼進(jìn)行了分析介紹,需要的朋友可以參考下2013-07-07深入C語(yǔ)言內(nèi)存區(qū)域分配(進(jìn)程的各個(gè)段)詳解
一般情況下,一個(gè)可執(zhí)行二進(jìn)制程序(更確切的說(shuō),在Linux操作系統(tǒng)下為一個(gè)進(jìn)程單元,在UC/OSII中被稱為任務(wù))在存儲(chǔ)(沒(méi)有調(diào)入到內(nèi)存運(yùn)行)時(shí)擁有3個(gè)部分,分別是代碼段(text)、數(shù)據(jù)段(data)和BSS段。這3個(gè)部分一起組成了該可執(zhí)行程序的文件2013-07-07如何使用C語(yǔ)言實(shí)現(xiàn)平衡二叉樹(shù)數(shù)據(jù)結(jié)構(gòu)算法
對(duì)于判斷是否為平衡二叉樹(shù)而言,我們需要知道以下特性:是一個(gè)二叉樹(shù)也是一個(gè)二叉排序樹(shù)該樹(shù)的每個(gè)結(jié)點(diǎn)上的(深度)左子樹(shù) - 右子樹(shù)的值為平衡因子(BF(Balance Factor))該樹(shù)的每一個(gè)節(jié)點(diǎn)的左子樹(shù)和右子樹(shù)的高度至多等于1(平衡因子只可能是-1,0,1)2021-08-08C++?OpenCV裁剪圖片時(shí)發(fā)生報(bào)錯(cuò)的解決方式
在圖像處理中,我們經(jīng)常根據(jù)需要截取圖像中某一區(qū)域做處理,下面這篇文章主要給大家介紹了關(guān)于C++?OpenCV裁剪圖片時(shí)發(fā)生報(bào)錯(cuò)的解決方式,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07解析C++中四種強(qiáng)制類型轉(zhuǎn)換的區(qū)別詳解
本篇文章是對(duì)C++中四種強(qiáng)制類型轉(zhuǎn)換的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05基于C++的攝像頭圖像采集及拼接程序的簡(jiǎn)單實(shí)現(xiàn)
本程序是在?ubuntu14.04?平臺(tái)下實(shí)現(xiàn)的,在本項(xiàng)目目錄下,已經(jīng)有編譯生成的可執(zhí)行程序,其中Camera_to_Frmae.cpp是我們從雙攝像頭實(shí)時(shí)抓取單幀圖像的源碼,對(duì)基于C++的攝像頭圖像采集及拼接程序的實(shí)現(xiàn)感興趣的朋友一起看看吧2022-01-01