C++ map set
map 和 set 的內部數據結構是紅黑樹
PS:二叉樹的存儲方式
二叉樹既可以用鏈式存儲,也可以用數組順序存儲。數組順序存儲的方式比較適合完全二叉樹,其他類型的二叉樹用數組存儲會比較浪費存儲空間。堆其實就是一種完全二叉樹,最常用的存儲方式就是數組。
PSS: 散列表 vs 二叉查找(排序)樹
-
散列表中的數據是無序存儲的,如果要輸出有序的數據,需要先進行排序。而對於二叉查找樹來說,我們只需要中序遍歷,就可以在 O(n) 的時間復雜度內,輸出有序的數據序列。
-
散列表擴容耗時很多,而且當遇到散列沖突時,性能不穩定,盡管二叉查找樹的性能不穩定,但是在工程中,我們最常用的平衡二叉查找樹的性能非常穩定,時間復雜度穩定在 O(logn)。
-
散列表的構造比二叉查找樹要復雜,需要考慮的東西很多。比如散列函數的設計、沖突解決辦法、擴容、縮容等。平衡二叉查找樹只需要考慮平衡性這一個問題,而且這個問題的解決方案比較成熟、固定。
-
盡管散列表的查找等操作的時間復雜度是常量級的,但因為哈希沖突的存在,這個常量不一定比 logn 小,所以實際的查找速度可能不一定比 O(logn) 快。加上哈希函數的耗時,也不一定就比平衡二叉查找樹的效率高。
紅黑樹
我們學習數據結構和算法,要學習它的由來、特性、適用的場景以及它能解決的問題。對於紅黑樹,也不例外。你如果能搞懂這幾個問題,其實就已經足夠了。
紅黑樹是一種平衡二叉查找樹。它是為了解決普通二叉查找樹在數據更新的過程中,復雜度退化的問題而產生的。紅黑樹的高度近似 log2n,所以它是近似平衡,插入、刪除、查找操作的時間復雜度都是 O(logn)。
map 和 set 使用
- map
// ref: https://blog.csdn.net/bingtang_blog/article/details/52730530
#include<iostream>
#include<map>
using namespace std;
int main(){
//map聲明,加入有文件map
map<int, int> m;
//插入元素要用makr_pair的方式
m.insert(make_pair(1, 5));
//通過iterator來查找map里面的元素
map<int, int>::iterator ite;
ite = m.find(1);
//如果找到了,那么我們就刪除掉原有的元素,加入新元素
//因為后來加入的元素如果鍵重復,不能覆蓋,會被忽略
if(ite != m.end()){
m.erase(1);
m.insert(make_pair(1, 6));
}else{
//沒找到直接加入
m.insert(make_pair(1, 6));
}
//用這種方式,來輸出鍵值對的值
cout << ite->second << endl;
//歷遍map元素,並輸出鍵值對
for(ite = m.begin(); ite != m.end(); ite++){
cout << ite->first << "\t" << ite->second << endl;
}
}
- set
// ref: https://blog.csdn.net/bingtang_blog/article/details/52730530
#include<iostream>
#include<map>
#include<set>
using namespace std;
int main(){
//聲明集合,加入頭文件<set>
set<int> s;
//向集合中插入元素
s.insert(1);
s.insert(2);
s.insert(3);
//在集合中查找元素
set<int>::iterator ite;
ite = s.find(1);
if(ite == s.end()){
cout << "Not found" << endl;
}else{
cout << "Found" << endl;
}
//集合刪除元素
s.erase(2);
//在集合中查找元素的第二種方式
if(s.count(3) != 0){
cout << "Found" << endl;
}else{
cout << "Not found" << endl;
}
//歷遍集合元素
for(ite = s.begin(); ite != s.end(); ite++){
cout << *ite << endl;
}
}