跳轉到內容

最佳化 C++/通用最佳化技術/其他技術

來自華夏公益教科書,開放的書籍,為開放的世界

查詢遊標

[編輯 | 編輯原始碼]

不要定義一個返回集合(也稱為快照)的函式,而要定義一個返回迭代器(也稱為遊標動態集)的函式,您可以使用它來生成或可能更改所需資料。

此技術對於資料庫查詢特別有用,但也適用於內部資料結構。

假設您有一個封裝在類中的集合(或一組集合)。該類公開了一個或多個成員函式來從該集合中提取(或過濾)一個子集。

一種獲取它的方法是構造一個新的集合,將提取的資料複製到其中,然後返回該集合。在資料庫術語中,這種集合被稱為快照

這種技術有效但效率低下,因為快照的分配和複製需要大量時間和儲存空間。此外,它還有一個缺點,即在所有資料都被提取之前,您無法繼續處理已經提取的資料。

這裡有一個等效但效率更高的技術。

查詢函式返回一個迭代器。在資料庫術語中,這種迭代器被稱為遊標動態集。呼叫者使用這種迭代器一次提取一個被過濾的資料,並可能更改它們。

請注意,這個解決方案並不完全等效,因為如果在迭代器使用過程中,集合被另一個函式呼叫(可能是來自另一個執行緒)更改,則迭代器可能被無效化,或者只是被過濾的集合不符合指定條件。因此,您只能在確定底層集合在迭代器整個生命週期內不會以任何方式更改(除了迭代器本身)的情況下應用此技術。

這種技術與程式語言無關,因為迭代器概念是一個抽象設計模式。

[編輯 | 編輯原始碼]

如果您需要在很少改變的集合中進行多次搜尋,而不是使用搜索樹或雜湊表,如果您將資料放入陣列,對陣列進行排序,並在其上執行二分搜尋,則可以提高速度。

陣列上的二分搜尋具有對數複雜度,與搜尋樹一樣,但具有陣列典型的緊湊性和區域性性引用優勢。

如果陣列發生了改變,只要改變的頻率遠低於搜尋頻率,這個演算法仍然具有競爭力。

如果每個集合更改都包含很少的元素插入或更改或刪除,則最好在每次更改操作時移動陣列。相反,如果集合更改更繁瑣,則最好重新建立並對整個陣列進行排序。

在 C++ 中,如果陣列長度不是編譯時常量,請使用 vector

單鏈表

[編輯 | 編輯原始碼]

如果對於列表,您不需要雙向迭代器,也不需要在當前元素的末尾或之前插入元素,並且您不需要知道列表中存在多少元素,請使用單鏈表,而不是雙鏈表

這種容器雖然有很多缺點,但佔用的空間更少,速度也更快。

通常,雙鏈表的表頭包含指向列表頭的指標,指向尾部的指標,以及元素計數器,而單鏈表的表頭只包含指向列表頭的指標。此外,通常,雙鏈表的每個節點都包含一個指向前一個節點的指標和一個指向下一個節點的指標,而單鏈表的每個節點只包含一個指向下一個節點的指標。最後,在雙鏈表中插入每個元素都必須更新四個指標並增加一個計數器,而在單鏈表中插入每個元素只需要更新兩個指標。

在 C++ 標準庫中,std::list 容器由雙鏈表實現。slist 容器是非標準的,但在各種庫中可用,以及forward_list 容器,它將在 C++11 標準庫中可用,由單鏈表實現。

華夏公益教科書