演算法學習之路|用C++刷演算法會用到的STL(二)——set
二、set
1.set的自我介紹
<li>set意思是集合,從初中就接觸到了集合的概念,真是的好東西。set是一個內部自動有序且不含重複元素的容器。</li>
<li>set是一種關聯式容器,是用來儲存同一種資料型別的資料型別,有點繞口,就是sety也就是集合裡裡面要不然全部裝int型的要不然全部裝double型的要不然....就是這個意思。並且能從這個同一種資料型別構成的集合中取出元素,而且set中的每個元素都是唯一的,不能重複,好像是數學裡集合概念中的唯一性(哈哈哈,強大的數學功底)。更令人欣慰的是,能根據元素的值進行自動排序。</li>
<li>一個集合(set)是一個容器,它其中所包含的元素的值是唯一的。這在收集一個資料的具體值的時候是有用的。集 閤中的元素按一定的順序排列,並被作為集合中的例項。如果你需要一個鍵/值對(pair)來儲存資料,map是一個更好的選擇。一個集合通過一個連結串列來組 織,在插入操作和刪除操作上比向量(vector)快,但查詢或新增末尾的元素時會有些慢。(原因後文簡單說說)</li>
<li>要注意的是,set中書元素的值不能被直接改變。C++ STL中標準關聯容器set, multiset, map, multimap內部採用的就是一種非常高效的平衡檢索二叉樹,即一種自平衡二叉樹(以後會講到啥叫平衡二叉樹~~):紅黑樹,也成為RB樹(Red-Black Tree)。RB樹的統計效能要好於一般平衡二叉樹,所以被STL選擇作為了關聯容器的內部結構。</li>
2.set的定義
<li>單獨定義一個set:</li>
set<typename> setname;
<li>其定義和大部分STL的定義都差不多,這裡的typename依然一樣可以是任何基本型別,比如int,double,char,結構體啊,還有STL的標準容器vector,set,queue啊等等。</li>
<li>需要注意的是,比如<em>set<vector<int> > setname;</em>兩個`>‘之間一定要加上空格,否則會編譯錯誤,原因是會誤以為位移運算(詳見上篇)。</li>
<li>特別的,set陣列:</li>
set<typename> Arrayname[arraySize];
比如,set<int>a[100];定義了一個set型的陣列,陣列中每一個數都是一個集合,每一個集合裡都是int型的值。
3.set容器內元素的訪問形式
<li>只有一種!</li>
hhh,選擇
困難症的同學是不是很開森呢?
只能通過迭代器訪問(啥叫迭代器?詳見上篇):
set<typename>::iterator it;(這個也不多說了,和vector是一模一樣滴)
比如,set<int>::iterator it;
set<double>::iterator it;
同樣的,和vector一樣可以通過*it來訪問set裡的元素啦,忍不住再嘮叨一句,迭代器就是指標。
4.set中的基本操作
<li>insert(x): 插入元素,並且自動遞增排序噢,而且去重,時間複雜度O(logN),N為set中元素的個數。</li>
<li>insert(first,second): 將定位器first到second之間的元素插入到set中,返回值是void</li>
<li>find(value): 返回set中對應值為value的迭代器,時間複雜度未O(logN)!!後文會重點講(見下文5.set的注意點和優良特性),有助於加深理解O(logN),舉一反三,以後也不過多強調了qwq。</li>
<li>begin(): 返回set容器的第一個元素//橋黑板!!begin() 和 end()函式是不檢查set是否為空的,使用前最好使用empty()檢驗一下set是否為空</li>
<li>end(): 返回set容器的最後一個元素</li>
<li>clear(): 刪除set容器中的所有的元素//時間複雜度O(N)</li>
<li>empty(): 判斷set容器是否為空</li>
<li>max_size(): 返回set容器可能包含的元素最大個數</li>
<li>size() : 返回當前set容器中的元素個數//時間複雜度O(1),賊快!</li>
<li>rbegin: 返回的值和end()相同</li>
<li>rend(): 返回的值和rbegin()相同</li>
<li>count(): 顧名思義嘛,用來查詢set中某個某個鍵值出現的次數。但是,這個函式在set並不是很實用,因為一個鍵值在set只可能出現0或1次,這樣就變成了判斷某一鍵值是否在set出現過了。(小技巧)</li>
<li>erase(iterator): 刪除迭代器iterator指向的值//時間複雜度O(1),賊快!注意和erase(value)不同噢</li>
<li>erase(first,second): 刪除定位器first和second之間的值(美國人的思維是左閉右開,最後一次強調)</li>
<li>erase(value): 刪除值為value的元素,時間複雜度O(logN)//橋黑板!!set中的刪除操作是不進行任何的錯誤檢查的,比如定位器的是否合法等等,所以用的時候自己一定要注意。</li>
<li>lower_bound(key_value): 返回第一個大於等於key_value的定位器</li>
<li>upper_bound(key_value): 返回最後一個大於等於key_value的定位器//二分啦!</li>
5.set的注意點和優良特性
(加深對set的理解,初學者可以先跳過此部分)
<li>不能直接改變元素值,因為那樣會打亂原本正確的順序,要改變元素值必須先刪除舊元素,則插入新元素</li>
<li>不提供直接存取元素的任何操作函式,只能通過迭代器進行間接存取,而且從迭代器角度來看,元素值是常數</li>
<li>元素比較動作只能用於型別相同的容器(即元素和排序準則必須相同)
因為set中重寫比較函式的用的真還不多,所以就不細細的講了,等降到後面的priority_queue的時候,我會重新講一下結構體的比較函式(其實也叫優先順序設定)。
從原型可以看出,可以看出比較函式物件及記憶體分配器採用的是預設引數,因此如果未指定,它們將採用系統預設方式,
另外,利用原型,可以有效地輔助分析建立物件的幾種方式。
之前提到了set(map也一樣哈)的插入刪除效率比用其他序列容器高,簡單的講set容器內所有元素都是以節點的方式來儲存,其節點結構和連結串列差不多,指向父節點和子節點。需要插入或刪除,只要改變指標指向的節點就可以啦。(其實本質上還是因為set自帶的紅黑樹的內部結構,就是外掛啊。氣哭!STL容器各個都是身懷絕技)
set中查詢是使用二分查詢,也就是說,如果有16個元素,最多需要比較4次就能找到結果,有32個元素,最多比較5次。那麼有10000個呢?最多比較的次數為log10000,最多為14次,如果是20000個元素呢?最多不過15次。看見了吧,當資料量增大一倍的時候,搜尋次數只不過多了1次,多了1/14的搜尋時間而已。你明白這個道理後,就可以安心往裡面放入元素了。
6.set的常見用途
set最主要的作用是自動去重,並在沒有寫比較函式的情況下,預設按升序排序,因此碰到需要去重但是卻不方便直接開陣列的情況,可以嘗試用set來解決噢。
set/multiset會根據待定的排序準則,自動將元素排序。兩者不同在於前者不允許元素重複,而後者允許。
7.練習題,橋黑板!!
PAT A1063. Set Similarity (25)
參考:C++中關於set的自定義排序函式的書寫,STL中set容器的一點總結
相關文章
- 演算法學習之路|用C++刷演算法會用到的STL(一)——vector演算法C++
- 演算法學習之路|用C++刷演算法會用到的STL(三)——string演算法C++
- C++ 學習筆記(1):STL、Vector 與 SetC++筆記
- 【C++ STL】Set用法C++
- 演算法學習之路|划拳演算法
- C++ STL演算法總結C++演算法
- 【演算法學習】STL庫 大小根堆的用法演算法
- 演算法學習之路|A除以B演算法
- 演算法學習之路|列印排名演算法
- 演算法學習之路|方格分割演算法
- 演算法學習之路|朋友數演算法
- 演算法學習之路|SpellItRight演算法
- 演算法學習之路|歐幾里得遊戲演算法遊戲
- 演算法學習之路|月餅演算法
- 演算法學習之路|PATRanking演算法
- 演算法學習之路|列印沙漏演算法
- 演算法學習之路|快速排序演算法排序
- 演算法學習之路|結繩演算法
- 演算法學習之路|數零壹演算法
- 演算法學習之路|二分圖的最大匹配—匈牙利演算法(Dfs實現)演算法
- C++ STL學習——vectorC++
- 演算法學習之路|開學寄語演算法
- 演算法學習之路|說反話演算法
- 演算法學習之路|幼兒園買玩具演算法
- 演算法學習之路|小賭怡情演算法
- 演算法學習之路|影像過濾演算法
- 演算法學習之路|日期問題演算法
- 演算法學習之路|賣個萌演算法
- 演算法學習之路|螺旋矩陣演算法矩陣
- 演算法學習之路|選擇題演算法
- 演算法學習之路|字元統計演算法字元
- C++ STL學習之stack。C++
- 演算法學習之路|最小生成樹——prime演算法演算法
- 演算法學習記錄二(C++)--->字串空格替換演算法C++字串
- 演算法學習之路|科學計數法演算法
- 演算法學習記錄十四(C++)--->二叉樹的映象演算法C++二叉樹
- 演算法學習之路|PlayOnWords(尤拉道路+dfs)演算法
- 演算法學習之路|舊鍵盤打字演算法