簡體   English   中英

C ++:二進制搜索樹end()迭代器

[英]C++: Binary search tree end() iterator

我有BST的基本(無隨機化,排序等)實現。 我想添加迭代器實現並使BST適用於基於范圍的for循環。 因此,我需要begin(),end()成員函數和迭代器遞增。

我知道begin()應該做什么-將迭代器返回到最左下角的節點,並且該線程討論了遍歷BST的不同可能性(=增加迭代器)

但是end()應該將迭代器賦予最后一個元素。 這是我不理解的實際問題,在BST的背景下,這是什么意思?

結束迭代器不必一定是最后一個元素之后的元素(對於矢量有意義,但對於樹而言則不那么有意義)。 它必須只是一個可以清楚地標識為不是用於指示已到達數據結構末尾的有效迭代器的迭代器。

實際上,這可以通過多種方式完成,具體取決於迭代器如何引用其指向的內容。 如果例如使用指向樹節點的指針,則可以將空指針用作結束迭代器。

一個非常簡單的使用兩個額外指針的內存的方案是將一個雙向鏈接的循環列表簡單地覆蓋在BST的頂部。 然后,您的end()迭代器僅指向一個前哨節點。 這也使您的迭代器增加/減少非常簡單。

BST::iterator &
BST::iterator::operator++() {
  n = n->next;
  return *this;
}

注意,像這樣使用哨兵意味着end迭代器不需要特殊處理。 您可以減少它並獲得完全正確的行為。

盡管有我的評論,桑德·戴克(Sander De Dycker)的想法正確。 我有另一種思考方式。

所有支持迭代器的容器都具有邏輯順序。 對於vector ,排序基於插入的完成方式-索引/下標排序。 對於mapset它基於鍵順序。 對於multimapmultiset ,兩者都有一點。 對於unordered_map等,聲明是非常脆弱的,但是我仍然可以討論哈希算法和沖突處理。

按照邏輯順序,您可以引用有序元素,但是有時引用每個元素之間的邊界是有意義的。 從邏輯上講(在某些情況下甚至對於實現而言),這樣做也很方便。

|     |     |     |     |     |     |     |     |
| +-+ | +-+ | +-+ | +-+ | +-+ | +-+ | +-+ | +-+ |
| |0| | |1| | |2| | |3| | |4| | |5| | |6| | |7| |
| +-+ | +-+ | +-+ | +-+ | +-+ | +-+ | +-+ | +-+ |
|     |     |     |     |     |     |     |     |
0     1     2     3     4     5     6     7     8

您可以確定零“綁定”的去向與零項的去向無關,但是始終可以獲得簡單的加/減關系。 如果最小邊界的編號與最小元素的編號相同,則最后一個邊界的編號比最后一個元素的編號大一個。 因此end作為一個過去的最終元件。

在二叉樹實現中,每個節點都可以視為具有兩個邊界-元素的任一側。 在此方案中,除beginend之外的每個界限都發生兩次。 您可以使用元素0的RHS或LHS或元素1來表示邊界1。因此,原則上可以使用節點指針和標志。 但是,您可能會選擇最方便的一種方法,而不是針對大多數范圍使用兩種方法,一種方法是不僅指的是右邊界,而且還指的是在取消引用時要查看的元素。 這意味着僅在引用end時設置標志,在這種情況下,您無論如何都不支持取消引用。

IOW遵循此邏輯可以告訴您,盡管我認為它仍然是一個有用的思維模型,但您實際上並不需要遵循此邏輯。 您真正需要的只是end的可識別表示。 對於該表示形式,包括指向最終指針的指針(作為例如減少該迭代器的起點)也許很有用。 也許在某些情況下,內部讓偽迭代器將兩個等效邊界識別為不同是很方便的。

考慮到例如多路樹(multiway tree),其中每個節點包含一個元素數組,出現了相似但略有不同的模型和選擇。

基本上,我認為從心理上將綁定的位置識別為與項目位置相關但與項目位置相關的位置很有用,但是該心理模型不應限制您的實現選擇-可能會激發替代方法,但這只是一種心理模型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM