日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

红黑树边界问题

發(fā)布時間:2024/2/28 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 红黑树边界问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

SGI STL紅黑樹中迭代器的邊界值分析

前言

?

  一段程序最容易出錯的就是在判斷或者是情況分類的邊界地方,所以,應該對于許多判斷或者是情況分類的邊界要格外的注意。下面,就分析下STL中紅黑樹的迭代器的各種邊界情況。(注意:分析中STL使用的版本是SGI STL,由于不同的版本的STL具體實現細節(jié)不一樣,所以可能會有出入)。

?

一、begin()獲取第一個迭代器的自減

?

  begin()函數獲取的是一個容器的首迭代器,指向容器中的第一個元素(這里的第一個不一定是指儲存順序(物理)上的第一個,一般是指邏輯上的第一個,在紅黑樹中是指樹中的最左節(jié)點)。那么對于首個迭代器進行自減會怎樣?

(1)首迭代器指向(即最左節(jié)點)不是根節(jié)點

最左節(jié)點不是根節(jié)點,就是根節(jié)點有左子樹。那么第一個迭代器,指向一定是左子樹的最左節(jié)點。--begin() ,會調用的decrement()函數,該函數如下:

1 void decrement()2 {3 if (node->color == __rb_tree_red &&4 node->parent->parent == node)5 node = node->right;6 else if (node->left != 0) {7 base_ptr y = node->left;8 while (y->right != 0)9 y = y->right; 10 node = y; 11 } 12 else { 13 base_ptr y = node->parent; 14 while (node == y->left) { 15 node = y; 16 y = y->parent; 17 } 18 node = y; 19 } 20 }

?

  因為第一個迭代器是執(zhí)行最左節(jié)點,所以其沒有左子樹,node->parent->parent也不等于node,所以他會回溯,找到第一個node 不是其父節(jié)點的左節(jié)點,那么他的父節(jié)點就是其結果。由于最左節(jié)點上溯不可能會有節(jié)點不是其父節(jié)點的左節(jié)點,那么while的最后一個循環(huán)時,node指向根節(jié)點,y指向header節(jié)點,此時node != y->left,(y->left指向就是最左節(jié)點),那么循環(huán)結束node = y,即指向了header節(jié)點,也是end().

?

?

(2)首迭代器指向(最左節(jié)點)是根節(jié)點

  最左節(jié)點就是根節(jié)點,這就說明根節(jié)點沒有左子樹。此時--begin(),同樣也是調用的decrement()函數,此時node->parent->parent != node,同時最左節(jié)點也沒有左子樹。那么函數會進入while循環(huán),第一次y指向頭結點(header指向的節(jié)點),node即是根節(jié)點,也是最左節(jié)點,循環(huán)條件滿足,node == y->left(即最左節(jié)點),進入循環(huán),node = y,node現在是頭結點了,y = y->parent,指向根節(jié)點了,(頭結點的parent是根節(jié)點,這是實現的技巧)。此時y->left,即根節(jié)點的左子節(jié)點,根沒有左子樹,所以為0,此時循環(huán)條件不滿足,跳出循環(huán),再node = y。即node又變?yōu)楦?jié)點了。即對于根沒有左子樹的紅黑樹,對--begin(),其結果還是begin()。

1 iterator it = rb_tree.begin(); 2 it == --it;

?

?

二、end()獲取last迭代器的自減

?

  last = end(); last指向的是頭結點(也這是紅黑樹實現中的技巧,header和end()都指向頭結點)。此時--last,會調用decrement函數,此時node即是頭結點,node->color == __rb_tree_red &&node->parent->parent == node,為真。(頭節(jié)點的顏色規(guī)定為紅,而且頭節(jié)點的parent是根節(jié)點,根節(jié)點的parent又是頭結點,所以node->parent->parent==node)。這時候node = node->right。頭結點的右節(jié)點,指向的紅黑樹的最右節(jié)點,最大的節(jié)點。此時--last,指向最大節(jié)點是正確的。

?

三、指向最右節(jié)點迭代器自增

?

  無論什么樣的情況,自增都是調用的increment()函數,那么就先上increment函數吧,如下:

1 void increment()2 {3 if (node->right != 0) {4 node = node->right;5 while (node->left != 0)6 node = node->left;7 }8 else {9 base_ptr y = node->parent; 10 while (node == y->right) { 11 node = y; 12 y = y->parent; 13 } 14 if (node->right != y) 15 node = y; 16 } 17 }

?

?

(1)最右節(jié)點不是根節(jié)點

  這種情況,就是根節(jié)點還有右子樹。這種情況下,對指向最右節(jié)點的迭代器自增,會調用上面increment函數。應該是指向最右節(jié)點,所以node->right == 0,所以只能上溯,找到其現行的節(jié)點不是其父節(jié)點的右節(jié)點。最右節(jié)點上溯,不可能會有現行的節(jié)點不是其父節(jié)點的右節(jié)點,while的最后一次循環(huán)時,node指向根節(jié)點,y指向頭結點(即end()指向的節(jié)點),這時,node != y->right(存儲的是最右節(jié)點),跳出循環(huán)。在判斷node->right != y,現在node是根節(jié)點,其有右節(jié)點不是頭結點,所以判斷結果為真,node=y,最后node為y,即頭結點,也就是end()返回的迭代器指向的節(jié)點,亦是last節(jié)點,指向最右的節(jié)點的迭代器自增,得到last迭代器,這是正確的。

(2)最右節(jié)點是根節(jié)點

如下圖

?

此時,指向最右的迭代器自增,調用increment函數,node->right == 0,進入while循環(huán)。y開始是node的parent,即頭結點,node == y->right(最右節(jié)點,此情況下即根節(jié)點),循環(huán)條件成立,進入循環(huán)。然后node = y,node變?yōu)轭^結點,y=y->parent(頭結點的parent即根節(jié)點),y變?yōu)楦?jié)點。此時判斷循環(huán)條件,y->right,即根節(jié)點的右子節(jié)點,這種情況下的根右子節(jié)點為空,node為頭結點不為空,循環(huán)條件不成立,跳出循環(huán)。接下來是

1 if (node->right != y) 2 node = y;

?

此時node是頭結點,其右節(jié)點就是樹的最右節(jié)點,這種情況下就是根節(jié)點,y就是根節(jié)點,那么if判斷條件不成立,返回的時候node就是頭結點,即end()返回迭代器指向的節(jié)點。此時迭代器就是last迭代器。對指向最右節(jié)點的迭代器自增,得到last迭代器,亦end()返回的迭代器,這是正確的。

?

結語

?

本文中討論了各種邊界情況,其中發(fā)現在SGI STL的紅黑樹中的一個有趣情況,對于迭代器first = begin(),其指向的節(jié)點是根節(jié)點的時候,(最左節(jié)點是根節(jié)點),對first自減得到的還是first。對于一些非邊界的迭代器的自增和自減,不是這里討論的范圍

總結

以上是生活随笔為你收集整理的红黑树边界问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。