紅黑樹的實現與驗證--c++
紅黑樹例項:
在說紅黑樹之前,我們先來認識一下它:
首先強調一點:紅黑樹也是二叉搜尋樹。那麼它就滿足二叉搜尋樹的性質,除此之外,他還有幾個比較特殊的性質,了解這些,有助於我們後面的分析
性質:1、紅黑樹所有的節點都有顏色(紅或黑)
2、紅黑樹的根結點是黑色的
3、紅黑樹的兩個紅色節點不能相連
4、紅黑樹的每一條鏈的黑節點的個數相同
5、所有空的節點都是黑色的
知道了這些之後開始進入紅黑樹的建立:
顯然這就是紅黑樹的插入操作的編寫了,那麼要想將乙個節點插入紅黑樹中,首先你得判斷紅黑樹是不是空的,如果是空的,那麼直接就可以插入;不是空的,那麼得找插入位置,然後再插入,這一點和二叉搜尋樹的插入是一樣的。不過需要注意,最後把根結點置成黑色的
插入?
插入的節點我們都預設為紅色的,但是性質3說,紅色的節點不能相鏈,如果,之後我們不管的話,性質3肯定不會滿足的,所以我們需要對紅黑樹進行調解,讓其滿足這些性質。那麼我們就需要分情況討論了,我們重點分析一下,兩個紅色節點相鏈的情況怎麼處理。
總共可以分為3種情況:
情況一:
雙親結點為紅色,祖先結點為黑色,叔叔節點存在,且為紅色
其實這個圖里包含了四種情況,我只是將其中的一種情況中的轉化後的形式畫了出來,其他的也一樣。
情況二:
雙親結點為紅色,祖先結點為黑色,叔叔節點不存在或存在為黑色
這種情況是:雙親在祖先節點的左的同時pcur在雙親的左;或是雙親在祖先節點的右的同時,pcur在雙親的右。
這樣我們就可以進行單旋處理,根據情況呼叫左單旋還是右單旋。
情況三:
雙親結點為紅色,祖先結點為黑色,叔叔節點不存在或存在為黑色
這個和情況二是互補的,情況二中剩下的都是不能單旋直接處理的,那麼就需要雙旋,圖中畫的是左右雙旋,先左旋之後,我們發現,和情況二的一樣,那麼**中這一塊就可以放在一起處理。
不過,這裡需要注意一點,就是,左旋之後只想pcur變成了雙親,而parent變成了孩子,所以,在第一次旋轉之後先對這兩個指標進行交換,在進行第二次旋轉。
驗證?
最後將插入寫完之後,我們可以寫乙個函式來測試一下這個是不是紅黑樹,這個其實也是對紅黑樹的性質的檢驗。其中重點驗證性質3和性質4。那麼我們來分析一下這步驟:
1、判斷這個樹是不是空樹,是的話,直接返回true
2、驗證性質2,判斷根結點的顏色是不是黑色的,是,返回true
3、要驗證性質三,得遍歷整個樹,而性質4的驗證也要這莫做,那麼我們將這兩個一起驗證。那麼首先我們得求出一條鏈的黑色節點的個數,並將其儲存起來,再遞迴遍歷左右子樹,驗證。
**?
#includeusing namespace std;
enum color ;
templatestruct rbtreenode
};templateclass rbtree
bool insert(const k& key, const v&value);
void _rotatel(node* parent);
void _rotater(node* parent);
void inorder();
void _inorder(node* proot);
bool checkrbtree();
bool _checkrbtree(node* proot,int counter,int k);
};//插入節點
templatebool rbtree::insert(const k&key, const v&value)
//尋找插入位置
node* pcur = _proot;
node* parent = null;
while (pcur)
else if (key > pcur->_key)
else
return false;
} //插入
pcur = new node(key, value);
if (key < parent->_key)
parent->_pleft = pcur;
else
parent->_pright = pcur;
pcur->_pparent = parent; //注意
//看紅黑樹是否滿足性質,分情況討論
while (_proot != pcur&&pcur->_pparent->_color == red)
else //情況二,三(將三轉化為二,再一起處理)
gf->_color = red;
parent->_color = black;
_rotater(gf);
}} else//雙親在右
else //情況
二、三(將情況三轉化為情況二,再一起處理)
gf->_color = red;
parent->_color = black;
_rotatel(gf);
}} }
_proot->_color = black;
return true;
}//左旋
templatevoid rbtree::_rotatel(node* parent)
//右旋
templatevoid rbtree::_rotater(node* parent)
templatevoid rbtree::inorder()
templatevoid rbtree::_inorder(node* proot)
}templatebool rbtree::checkrbtree()
//驗證性質4「每條鏈上的黑色結點都相等」,驗證性質3「紅色結點不能相連」
return _checkrbtree(_proot, blackcount, 0);
}templatebool rbtree::_checkrbtree(node* proot, int counter, int k)
return _checkrbtree(proot->_pleft, counter, k)
&& _checkrbtree(proot->_pright, counter, k);
}void testrbtree()
; //int a = ;
//int a = ;
rbtreet;
cout << "notorder: ";
for (int index = 0; index < sizeof(a) / sizeof(a[0]); index++)
cout << endl;
t.inorder();
if (t.checkrbtree())
cout << "是紅黑樹!" << endl;
else
cout << "不是紅黑樹!" << endl;
}int main()
紅黑樹(c實現)
學習紅黑樹原理,網路上有很多文章。學習紅黑樹的具體實現,個人推薦去看jdk中的treemap原始碼。因為該原始碼很簡潔,並且很容易改為其它語言的實現,最重要的是該份實現得到世人的認可,可以保證是沒問題的 下面是我根據其實現,使用c語言改寫的紅黑樹實現,目前只有紅黑樹的插入實現。include inc...
紅黑樹C 實現
完整實現了一遍紅黑樹,程式就當作自己的筆記好了 紅黑樹,顧名思義,就是紅黑相間的樹,它借由紅黑規則實現了二叉排序樹的平衡。紅黑規則如下 1.每個節點不是紅就是黑 2.根總是黑色 3.若節點為紅色,它的子節點必須為黑色 4.從根到葉的每條路徑,必須包含相同數目的黑色節點 插入和刪除節點時都要遵循紅黑規...
紅黑樹的C 實現
ifndef rbtree h define rbtree h include using namespace std define red 0 define black 1 template typename t class treenode treenode t value constructo...