算法筆記-基本資料結構
基礎資料結構
我們程式想儲存東西有很多種方式,而資料結構就像一種容器,
可以儲存或拿取需要的東西,每種資料結構都有不同的複雜度,
如果用得好,效率就會高。
以下都是最基本的資料結構
1.Vector - 向量 in <vector>
|
|
向量可當成陣列來用,應該說它就是更強的陣列,而且易維護。
比起原本陣列,它可以自動擴大容量,
能用的空間也比陣列還多。但要注意的是,如果使用operator[]存取了未配置的記憶體位置,
會導致Segmentation Fault。
以下為vector的功能:
-- vector[n] 存取索引值為n的元素
-- vector.at(n) 存取索引值為n的元素(較安全)
-- vector.begin() 回傳指向vector第一個元素的疊代器
-- vector.end() 回傳指向vector最後一個元素再下一個的疊代器
-- vector.front() 回傳vector[0]
-- vector.back() 回傳vector最後一個元素的值
-- vector.size() 回傳目前vector儲存了多少元素
-- vector.resize(n) 修改vector大小
-- vector.capacity() 存取可容納最大個數
-- vector.empty() 回傳布林值表示vector是不是空的
-- vector.reserve(n) 配置更多記憶體以容納更多元素
-- vector.push_back(n) 把n放到vector最尾端
-- vector.pop_back() 把vector最尾端元素取出
-- vector.insert(it,n) 在疊代器it後插入元素n
-- vector.erase(it,(it2)) 刪除疊代器it~it2的元素
-- vector.clear() 刪除所有元素
-- vector.swap(vector2) 交換兩個vector
以下是一個使用vector的範例:
|
|
2.Pair - 值對 in <utility>
把兩個變數綁成一個變數的結構。
而且不一定要一樣的型態才能綁。
可以使用make_pair(x,y) 來綁變數。
|
|
-- pair.swap(p2) 交換兩個pair
-- pair.first 得到pair前值
-- pair.second 得到pair後值
3.Stack - 堆疊 in <stack>
|
|
堆疊就像我們把東西一層一層往上疊,
當要拿取下面的東西時,只能先把上面的東西都先拿完才能拿,
即越後面丟進去的,就越早拿出來。
APCS觀念題:
若將5、8、34、10、199、123依序丟進Stack裡,求一個一個取出後會依序得到哪些值?
(A)5,8,34,10,199,123
(B)123,199,10,34,8,5
(C)5,8,10,34,123,199
(D)199,123,34,10,8,5
正確答案為(B)
以下為stack的成員函式:
-- stack.top() 回傳stack最頂端的資料
-- stack.push(x) 把x丟進堆疊裡
-- stack.pop() 把最頂端的資料刪除
-- stack.size() 回傳stack裡目前儲存多少東西
-- stack.empty() 回傳布林值表示stack是不是空的
4.Queue - 佇列 in <queue>
|
|
就像我們在排隊一樣,要加入元素只能加到尾端,
而要取出元素只能取最前端的資料。
以下為queue的成員函式:
-- queue.push(n) 把n加到queue尾端
-- queue.pop() 把queue最前端值刪除
-- queue.size() 回傳隊伍大小
-- queue.front() 回傳最前端的值
-- queue.empty() 回傳布林值表示queue是不是空的
5.Deque - 雙向佇列 in <deque>
|
|
與佇列不同的地方,就是可以加前面也能加後面,
刪除也是。
以下為deque的成員函式:
-- deque.front() 回傳最前端的值
-- deque.back() 回傳最尾端的值
-- deque.push_front(n) 把n加到前端
-- deque.push_back(n) 把n加到尾端
-- deque.pop_front() 把最前端的值刪除
-- deque.pop_back() 把最尾端的值刪除
-- deque.size() 回傳雙向佇列大小
6.Priority Queue - 優先佇列 in <priority_queue>
這種資料結構是一種Heap(堆積),
主要功能是維護極值,複雜度O(logN)。
其成員函數與queue差不多,但在宣告時可指定多種容器。
|
|
7.Set - 集合 in <set>
有自動排序的功能,是一棵紅黑樹,插入元素複雜度為O(logN)。
但沒有operator[]跟.at()能使用,必須用疊代器存取元素。
而且元素不能重複(會自動合併),也不能修改。
以下為set的成員函式:
-- set.insert(n) 新增n到set
-- set.erase(n) 把n從set中刪除
-- set.find(n) 回傳n的疊代器,如果沒找到會返回set.end()
-- set.count(n) 回傳n是否存在
-- set.begin() 回傳第一個元素的疊代器
-- set.end() 回傳指向set最後一個元素再下一個的疊代器
以下為遍歷set的兩種方式:
|
|
其他類似資料結構:
– multiset 可儲存重複元素。
– unordered_set hash結構,沒有排序功能但複雜度可到O(1),同時也消耗更多記憶體。
8.Map - 映射 in <map>
一樣可以自動排序,一個鍵值對應一個值,
而鍵值不可重複。
它是一棵紅黑樹,插入元素複雜度O(logN)。
|
|
成員函式同set,可以使用operator[]。
其他類似資料結構:
– unordered_map hash結構,沒有排序功能
9.DSU(Disjoint Set Union) - 並查集
如果遇到題目在詢問兩個元素是否在同一個集合,
或需要合併集合時會用到。
一開始,每個值的父節點設成他自己。
每個集合中所有元素都以某個值做為它的父節點,即所有節點都指向根。
|
|
當需要合併集合,只要把根節點指向另一集合。
|
|
最後整個結構程式長這樣:
|
|
10.BitSet - 位元集
可以把它當成一個bool array,也可以直接用它把數值轉成二進位形式,
它只能由0/1組成。
宣告的方式是 bitset<N> bs
,表示N位數的位元集,
初始化可以 bitset<N> bs(X)
,表示將X轉成N位數的二進位型態。
注意X可以是字串,但只能包含0/1,否則會RE。
如果X轉成二進位的位數超過宣告的位數,會直接省略高位的部分。
要輸出的話,直接 cout << bs;
就行。
若要對bitset進行位元運算,直接對其加上位元運算符號即可,
比如 b= b0 << 1;
(b 設為 b0左移一位元 )。
以下是Bitset的成員函式:
-- bitset.count() 回傳bitset有多少個1
-- bitset.size() 回傳bitset有多少位
(要知道0的個數就是兩個相減)
-- bitset.any() 回傳布林值表示bitset是否有1
-- bitset.none() 回傳布林值表示是否沒有1
-- bitset.flip(x) 將第x位元做NOT,如果不填x,就全部做NOT
-- bitset.set(x,n) 將第x位元設為n,如果不填x,就全部設成1
如果不填n,則設成1