C++ set(STL set)容器是什麼

2020-07-16 10:04:30
從本節開始,將介紹 set (集合)的使用。集合是一個簡單直觀的數學概念,即具有共同特徵的事物的集合。集合在 STL 中有兩個概念,它們都涉及一系列的數學思想。集合可以是由兩個疊代器定義的範圍內的一系列物件,也可以是一種有特殊特徵的容器型別。set 容器是關聯容器,其中的物件是物件它們自己的鍵。

除了沒有單獨的鍵,set 容器和 map 容器很相似。定義 set 的模板有 4 種,其中兩種預設使用 less<T> 來對元素排序,另外兩種使用雜湊值來儲存元素。有序 set 的模板定義在 set 標頭檔案中。無序 set 的模板定義在 unordered_set 標頭檔案中。因此有序 set 包含的元素必須支援比較運算,無序 set 中的元素必須支援雜湊運算。

定義 set 容器的模板如下:
  • set<T> 容器儲存 T 型別的物件,而且儲存的物件是唯一的。其中儲存的元素是有序的,預設用 less<T> 物件比較。可以用相等、不相等來判斷物件是否相同。
  • multiSet<T> 容器和 set<T> 容器儲存 T 型別物件的方式相同,但它可以儲存重複的物件。
  • unorderd_set<T> 容器儲存 T 型別的物件,而且物件是唯一的。元素在容器中的位置由元素的雜湊值決定。預設用 equal_to<T> 物件來判斷元素是否相等。
  • unordered_multiset<T> 容器儲存 T 型別物件的方式和 unorderd_set<T> 相同,但它可以儲存重複的物件。

從有序和無序關聯容器獲取的各種疊代器之間有一些區別。我們可以從有序容器得到正向和反向疊代器,但是只能從無序容器得到正向疊代器。

如果之前沒有用過 set 容器,你可能不知道如何檢索這種容器中的物件,這需要提供一個相同的物件。如果我們已經有這個物件,那為什麼還需要再去獲取它?對此你也許會感到驚訝,set 容器有很多用途。

和一組事物相關的程式可以用 set 來儲存候選資料,它可以確定程式需要的資料集。大學裡的班級就是一個範例。每個班都可以用一個包含學生的set容器來表示。這裡使用 set 容器比較合適,因為同一個班級中不可能有重複的學生;顯然,兩個學生可以同名,但是它們所表示的人是不同的。可以很容易檢視某個學生是否申請了某門課程,也可以檢視某個學生申請了哪些課程。

一般來說,當 set 中有大量元素時,在無序 set 上執行的隨機插入和檢索操作要比有序 set 快。在有 n 個元素的有序 set 中檢索元素的時間複雜度是 logn。在無序 set 中檢索元素的平均時間複雜度是常數,這和元素的個數無關,儘管實際效能會受元素雜湊操作和內部組織效率的影響。

物件在容器中的存放位置取決於有序 set 的比較函數和無序 set 的雜湊函數,對於儲存同一種物件的不同 set,我們可以使用不同的比較函數或雜湊函數。這裡有一個簡單的範例,用 Person 類來表示公司的員工,這個類會封裝一些個人資訊。類中應該包括個人 ID、部門、姓名、年齡、地址、性別、電話號碼、薪酬等級等資訊。然後可以用各種方式對員工進行分類。可以在一個 set 中用工作部門的雜湊比較,在另一個 set 中用薪酬等級的雜湊比較。這樣我們就可以得到特定薪酬等級或特定部門的員工。這些 set 中不會儲存重複的 Person 物件。可以在自由儲存區建立 Person 物件,然後將它們的智慧指標儲存在容器中。在本章的後面你會看到一些相關範例。為了簡化程式碼,假定在本章使用了 std::string。