STL庫——map/set(類函數學習)

? ? ? ? ?

づ?ど

?🎉?歡迎點贊支持🎉

個人主頁:勵志不掉頭發的內向程序員;

專欄主頁:C++語言;


文章目錄

前言

一、序列式容器和關聯式容器

二、set 系列的使用

2.1、set 和 multiset 參考文檔

2.2、set 類的介紹

2.3、set 的構造和迭代器

2.4、set 的增刪查

2.5、find 和 erase 使用樣例

2.6、multiset 和 set 的差異

三、map 系列的使用

3.1、map 和 multimap 參考文檔

3.2、map 類的介紹

3.3、pair 類型介紹

3.4、map 的構造和迭代器

3.5、map 的增刪查

3.6、map 的數據修改

3.7、map 的迭代器和 [ ] 功能樣例

3.8、multimap 和 map 的差異

總結


前言

本章節我們講解 map/set 這兩個容器,它和我們之前學習的容器不太一樣,要比我們之前學習的內容復雜的多,它的底層的大致框架就是我們上一章節的二叉搜索樹,所以學習本章節前希望大家對上一章的學習能夠充分掌握,這樣我們學習本章節時就會比較輕松啦,接下來我們一起看看吧。


一、序列式容器和關聯式容器

前面我們已經接觸過了 STL 中的部分容器如:string、vector、list、deque 等,這些容器我們統稱為序列容器,因為邏輯結構為線性序列的數據結構,兩個位置存儲的值之間一般沒有緊密的關聯關系,比如交換一下,它依舊是序列式容器。順序容器中的元素是按它們在容器中的存儲位置來按順序保存和訪問的。

關聯式容器也是用來存儲數據的,與序列式容器不同的是,關聯式容器的邏輯結構通常是非線性結構,兩個位置有緊密的關聯關系,交換一下,他的存儲結構就被破壞了。順序容器中的元素是按關鍵字來保存和訪問的。關聯式容器有 map/set 系列和 unordered_map/unordered_set 系列。

本章節所講解的 map 和 set 底層是紅黑樹,紅黑樹是一顆平衡二叉搜索樹(我們上一章節講了二叉搜索樹,明白了它的弊端,所以紅黑樹就是用來解決這種弊端的一種方法,后面會講)。set 是 key 搜索場景的結構,map 是 key/value 搜索場景的結構。

二、set 系列的使用

2.1、set 和 multiset 參考文檔

我們大家可以打開參考文檔查看:<set> - C++ Reference

2.2、set 類的介紹

set 的聲明如下,T 就是 set 底層關鍵字的類型

我們 set 就像優先級隊列一樣可以比較大小,我們上一章節也有說 set 的插入邏輯。set 默認要求 T 支持小于比較,如果不支持或者想按自己的需求走可以自行實現仿函數傳給第二個模板參數。

set 底層存儲數據的內存是從空間配置器中申請的,如果需要可以自己實現內存池,傳給第三個參數。一般情況下我們都不需要傳后兩個模板參數。

set 底層是用紅黑樹實現,增刪查的效率是 O(logN),迭代器遍歷是走的搜索樹的中序,所以是有序的。

2.3、set 的構造和迭代器

set 構造我們關注以下幾個接口即可。

1、無參的默認構造:

set<int> st1;

2、迭代器區間構造

vector<int> v({ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 });
set<int> st2(v.begin() + 1, v.end() - 2);

3、拷貝構造

set<int> st3(st2);

4、列表構造(C++11 后才支持)

set<int> st4({ 10, 11, 12, 13, 14, 15 });

set 支持正向和反向迭代遍歷,遍歷默認按照升序順序,因為底層是二叉搜索樹,迭代器遍歷走的中序;支持迭代器就意味著支持范圍 for,set 的 iterator 和 const_iterator 都不支持迭代器修改數據,修改關鍵字數據,破壞了底層搜索樹的結構。

set<int>::iterator it = st2.begin();
set<int>::reverse_iterator rit = st4.rbegin();while (it != st2.end())
{cout << *it << " ";it++;
}cout << endl;while (rit != st4.rend())
{cout << *rit << " ";rit++;
}cout << endl;

也是支持范圍 for 的。

for (auto e : st3)
{cout << e << " ";
}
cout << endl;

2.4、set 的增刪查

set 的增刪查關注以下幾個接口即可:

增:

單個數據插入,如果已經存在則插入失敗。

這里的 value_type 其實就是把 T 封裝一下。

set<int> st1;
st1.insert(1);
st1.insert(2);
st1.insert(2);
st1.insert(4);

迭代器區間插入,已經在容器中存在的值不會插入。

vector<int> v({ 1, 2, 3, 4, 5, 6, 7, 8, 9 });
set<int> st1({ 1, 2, 3 ,4 });
st1.insert(v.begin(), v.end());

列表插入,已經在容器中存在的值不會插入。

set<int> st1({ 1, 2, 3 ,4 });
st1.insert({3, 4, 5, 6, 7, 8});

查:

查找 val,返回 val 所在的迭代器,沒有找到返回 end()。

set<int> st1({ 1, 2, 3, 4, 5, 6, 7, 8, 9 });auto it = st1.find(4);
cout << *it << endl;
// 找不到就返回 end()
it = st1.find(0);
cout << *(--it) << endl;

查找 val,返回 val 的個數(我們雖然 set 不能保存多個相同的數據,但是 multiset 則可以保存,這個接口主要就是給 multiset 使用的)。

set<int> st1({ 1, 2, 3, 4, 5, 6, 7, 8, 9 });cout << st1.count(2) << endl;
cout << st1.count(0) << endl;

刪:

刪除一個迭代器位置的值。

set<int> st1({ 1, 2, 3, 4, 5, 6, 7, 8, 9 });
set<int>::iterator it = st1.begin();
it++;
it++;
it++;st1.erase(it);for (auto e : st1)
{cout << e << " ";
}
cout << endl;

刪除 val,val 不存在返回 0,存在返回 1

set<int> st1({ 1, 2, 3, 4, 5, 6, 7, 8, 9 });cout << st1.erase(5) << endl;
cout << st1.erase(100) << endl;for (auto e : st1)
{cout << e << " ";
}
cout << endl;

刪除一段迭代器區間的值。

set<int> st1({ 1, 2, 3, 4, 5, 6, 7, 8, 9 });st1.erase(++st1.begin(), --st1.end());for (auto e : st1)
{cout << e << " ";
}
cout << endl;

我們的刪除方式和我們上一章節講解的二叉搜索樹一樣的刪除方式,所以有可能直接刪除銷毀,會導致我們的迭代器指向野指針,也有可能是交換,此時迭代器指向的內容變了,所以我們認為迭代器失效了。

我們的查詢除了 find 和 count 還有兩個之前沒有講過的函數 lower_bound 和 upper_bound。

lower_bound 的作用是返回 >= val 位置的迭代器。

set<int> st1({ 1, 2, 3, 4, 5, 6, 7, 8, 9 });set<int>::iterator it = st1.lower_bound(4);while (it != st1.end())
{cout << *it << " ";++it;
}cout << endl;

upper_bound 的作用是返回 > val 位置的迭代器。

set<int> st1({ 1, 2, 3, 4, 5, 6, 7, 8, 9 });set<int>::iterator it = st1.upper_bound(4);while (it != st1.end())
{cout << *it << " ";++it;
}cout << endl;

2.5、find 和 erase 使用樣例

由于我們的 set 的 find 接口返回的是一個迭代器,而 set 的 erase 支持迭代器刪除,所以我們就可以使用 find 去查找我們想要刪除的值,然后調用 erase 刪除。

int main()
{set<int> s = { 4,2,7,2,8,5,9 };int x;// 直接查找在利?迭代器刪除xcin >> x;auto pos = s.find(x);if (pos != s.end()){s.erase(pos);}else{cout << x << "不存在!" << endl;}for (auto e : s){cout << e << " ";}cout << endl;return 0;
}

2.6、multiset 和 set 的差異

multiset 和 set 使用基本完全類似,主要區別點在于 multiset 支持值冗余,那么 insert/find/count/erase 都圍繞著支持值冗余有所差異。

int main()
{// 相?set不同的是,multiset是排序,但是不去重multiset<int> s = { 4,2,7,2,4,8,4,5,4,9 };auto it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;// 相?set不同的是,x可能會存在多個,find查找中序的第?個int x;cin >> x;auto pos = s.find(x);while (pos != s.end() && *pos == x){cout << *pos << " ";++pos;}cout << endl;// 相?set不同的是,count會返回x的實際個數cout << s.count(x) << endl;// 相?set不同的是,erase給值時會刪除所有的xs.erase(x);for (auto e : s){cout << e << " ";}cout << endl;return 0;
}

三、map 系列的使用

3.1、map 和 multimap 參考文檔

我們大家可以打開參考文檔查看:map - C++ Reference;

3.2、map 類的介紹

map 的聲明如下,Key?就是 set 底層關鍵字的類型,T 就是 map 底層 value 的類型。

set 默認要求 Key 支持小于比較,如果不支持或者需要的話可以自行實現仿函數傳給第二個模板參數,map 底層存儲數據的內存是從空間配置器申請的。一般情況下,我們都不需要傳后兩個模板參數。map 底層是用紅黑樹實現的,增刪查改的效率是 O(logN),迭代器遍歷是走的中序,所以是按 key 有序順序遍歷的。

3.3、pair 類型介紹

這里的 pair 是一個類模板,它里面有兩個成員,分別是 first 和 second。

我們如果把 key 傳給 T1 ,value 傳給 T2 的話,那 first 就對應 key,second 就對應 value。

我們可以來看看它的底層實現。

typedef pair<const Key, T> value_type;template <class T1, class T2>
struct pair
{typedef T1 first_type;typedef T2 second_type;T1 first;T2 second;pair() : first(T1()), second(T2()){}pair(const T1& a, const T2& b) : first(a), second(b){}template<class U, class V>pair(const pair<U, V>& pr) : first(pr.first), second(pr.second){}
};template <class T1, class T2>
inline pair<T1, T2> make_pair(T1 x, T2 y)
{return (pair<T1, T2>(x, y));
}

map 底層的紅黑樹結點中的數據,使用 pair<Key, T> 存儲鍵值對數據。

我們上一章節實現 key/value 是創建了兩個值,這里只不過是把這兩個值放在一個結構里面封裝起來了罷了。

3.4、map 的構造和迭代器

map 的構造我們關注以下幾個接口即可。

1、無參默認構造

map<int, int> mp1;

2、迭代器區間構造

vector<pair<int, int>> v({ {1,1}, {2, 2}, {3, 3}, {4, 4}, {5, 5} });
map<int, int> mp2(v.begin() + 1, v.end() - 1);

3、拷貝構造

map<int, int> mp3(mp2);

4、列表構造

map<int, int> mp4({ {10, 10}, {11, 11},  {12, 12}, {13, 13}, {14, 14} });

map 的支持正向和反向迭代遍歷,遍歷默認按 key 的升序順序,因為底層是?叉搜索樹,迭代器遍歷?的中序;?持迭代器就意味著?持范圍 for,map 支持修改 value 數據,不?持修改 key 數據,修改關鍵字數據,破壞了底層搜索樹的結構。

map<int, int>::iterator it = mp2.begin();
map<int, int>::reverse_iterator rit = mp2.rbegin();while (it != mp2.end())
{cout << it->first << " " << it->second << endl;++it;
}
cout << endl;while (rit != mp2.rend())
{cout << it->first << " " << it->second << endl;++it;
}
cout << endl;

我們這里因為 map 中存儲的是一個 pair 結構,而 pair 沒有重載流輸入和流輸出,所以此時我們就得自己去實現我們的輸入和輸出,而 pair 中就兩個數據,first 和 second。我們可以使用

(*it).first、(*it).second,或者直接使用箭頭即可。

當然也是支持范圍 for 的。

for (auto e : mp4)
{cout << e.first << " " << e.second << endl;
}cout << endl;

也可以試著修改 value。

map<int, int>::iterator it = mp2.begin();while (it != mp2.end())
{cout << it->first << " " << it->second << endl;++it;
}
cout << endl;it = mp2.begin();while (it != mp2.end())
{++it->second;cout << it->first << " " << it->second << endl;++it;
}
cout << endl;

3.5、map 的增刪查

map 的增刪查關注以下幾個接口即可:

map 增的接口,插入的 pair 鍵值對數據,跟 set 所有不同,但是查和刪的接口只用關鍵字 key 跟set 是完全類似的,不過 find 返回 iterator,不僅僅可以確認 key 在不在,還找到 key 映射的 value,同時通過迭代還可以修改 value。

增:

1、單個數據插入,如果已經 key 存在則插?失敗,key 存在相等 value 不相等也會插?失敗。

map<int, int> mp1;
pair<int, int> kv1 = { 3, 2 };
pair<int, int> kv2 = { 4, 1 };mp1.insert(pair<int, int>( 1, 1 ));
mp1.insert(pair<int, int>( 2, 1 ));
mp1.insert(pair<int, int>( 2, 1 ));
mp1.insert(pair<int, int>( 3, 1 ));
mp1.insert(kv1);
mp1.insert(kv2);

我們的 pair 就和對象一樣直接調用即可。只輸出了 4 個值,只要 key 相同就只會插入第一次出現的那個 key/value。但是我們這樣調用十分的麻煩,不是特別方便,所以我們引入了一個make_pair。

有了這個類型,我們可以直接把 key 和 value 傳給 map, 它會自動推導類型,推導成功后構造一個 pair 進行返回。

map<int, int> mp1;
mp1.insert(make_pair(1, 1));
mp1.insert(make_pair(2, 1));
mp1.insert(make_pair(2, 1));
mp1.insert(make_pair(3, 1));
mp1.insert(make_pair(3, 2));
mp1.insert(make_pair(4, 1));

C++11 后支持多參數的隱式類型轉換,此時我們便支持這種方式了。

map<int, int> mp1;
mp1.insert({ 1, 1 });
mp1.insert({ 2, 1 });
mp1.insert({ 2, 1 });
mp1.insert({ 3, 1 });
mp1.insert({ 3, 2 });
mp1.insert({ 4, 1 });

2、列表插入,已經在容器中存在的值不會插入。

map<int, int> mp1;
mp1.insert({ {1, 2}, {1, 3}, {2, 3}, {2, 3}, {3, 3}, {4, 3} });

3、迭代器區間插入,已經在容器中存在的值不會插入。

map<int, int> mp1;
mp1.insert({ {1, 2}, {1, 3}, {2, 3}, {2, 3}, {3, 3}, {4, 3} });
vector<pair<int, int>> v({ {1, 3}, {10, 2}, {3, 7}, {5, 10}, {100, 1} });
mp1.insert(v.begin(), v.end());

查:

1、查找k,返回k所在的迭代器,沒有找到返回end()。

map<int, int> mp1;
mp1.insert({ {1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7} });auto it1 = mp1.find(2);
cout << it1->first << " " << it1->second << endl;
auto it2 = mp1.find(9);
it2--;
cout << it2->first << " " << it2->second << endl;

2、查找k,返回k的個數。

map<int, int> mp1;
mp1.insert({ {1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7} });auto it1 = mp1.count(2);
cout << it1 << endl;
auto it2 = mp1.count(9);
cout << it2 << endl;

刪:

1、刪除?個迭代器位置的值。

map<int, int> mp1;
mp1.insert({ {1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7} });map<int, int>::iterator it = mp1.begin();
it++;
it++;
it++;
mp1.erase(it);

2、刪除k,k存在返回0,存在返回1。

map<int, int> mp1;
mp1.insert({ {1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7} });cout << mp1.erase(2) << endl;
cout << mp1.erase(100) << endl;

3、刪除?段迭代器區間的值。

map<int, int> mp1;
mp1.insert({ {1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7} });mp1.erase(++mp1.begin(), --mp1.end());

我們 map 也有 lower_bound 和 upper_bound 這兩個接口。和我們的 set 的功能是一樣的,也是比較 key,查找大于或大于等于 key 的所有值。

int main()
{map<int, int> mp;for (int i = 1; i < 10; i++)mp.insert({ i * 10, 1 }); // 10 20 30 40 50 60 70 80 90for (auto e : mp){cout << e.first << " " << e.first << endl;}cout << endl;// 實現查找到的[itlow,itup)包含[30, 60]區間// 返回 >= 30auto itlow = mp.lower_bound(30);// 返回 > 60auto itup = mp.upper_bound(60);// 刪除這段區間的值mp.erase(itlow, itup);for (auto e : mp){cout << e.first << " " << e.first << endl;}cout << endl;return 0;
}

3.6、map 的數據修改

  • 前?我提到 map 支持修改 mapped_type 數據,不支持修改 key 數據,修改關鍵字數據,破壞了底層搜索樹的結構。
  • map 第?個支持修改的方式是通過迭代器,迭代器遍歷時或者 find 返回 key 所在的 iterator 修改,map 還有?個?常重要的修改接口 operator[ ],但是 operator[ ] 不僅僅支持修改,還?持插?數據和查找數據,所以他是?個多功能復合接口。
  • 需要注意從內部實現?度,map 這?把我們傳統說的 value 值,給的是 T 類型,typedef 為mapped_type。? value_type 是紅?樹結點中存儲的 pair 鍵值對值。?常使?我們還是習慣將這?的 T 映射值叫做 value。

我們迭代器修改只能對 pair 的第二個值 value 進行修改,不能對第一個值進行修改。

int main()
{map<int, int> mp1;mp1.insert({ {1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7} });for (auto e : mp1){cout << e.first << " " << e.second << endl;}cout << endl;map<int, int>::iterator it = mp1.begin();while (it != mp1.end()){(it->second)++;cout << it->first << " " << it->second << endl;it++;}return 0;
}

我們 operator[ ] 函數,如果 [ ] 中的 key 值存在的話,那就是修改。

map<int, int> mp1;
mp1.insert({ {1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7} });mp1[2] = 200;
mp1[3] = 300;
mp1[4] = 400;
mp1[5] = 500;

如果 [ ] 中的 key 值不存在的話,那就是插入。

map<int, int> mp1;
mp1.insert({ {1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7} });mp1[10] = 2;
mp1[20] = 3;
mp1[30] = 4;
mp1[40] = 5;

3.7、map 的迭代器和 [ ] 功能樣例

1、

using namespace std;
int main()
{map<string, string> dict;dict.insert(make_pair("sort", "排序"));// key不存在->插? {"insert", string()}dict["insert"];// 插?+修改dict["left"] = "左邊";// 修改dict["left"] = "左邊、剩余";// key存在->查找cout << dict["left"] << endl;return 0;
}

2、

int main()
{// 利?find和iterator修改功能,統計數字出現的次數string arr[] = { "1", "2", "1", "2", "1", "1", "2","1", "3", "1", "3" };map<string, int> countmap;for (const auto& str : arr){// 先查找數字在不在map中// 1、不在,說明數字第?次出現,則插?{數字, 1}// 2、在,則查找到的節點中數字對應的次數++auto ret = countmap.find(str);if (ret == countmap.end()){countmap.insert({ str, 1 });}else{ret->second++;}}for (const auto& e : countmap){cout << e.first << ":" << e.second << endl;}cout << endl;return 0;
}

3.8、multimap 和 map 的差異

multimap 和 map 的使用基本完全類似,主要區別點在于 multimap 支持關鍵值 key 冗余,那insert/find/count/erase 都圍繞著支持關鍵值 key 冗余有所差異,這?跟 set 和 multiset 完全?樣,比如 find 時,有多個 key,返回中序第?個。其次就是 multimap 不支持 [ ],因為支持 key 冗余, [ ] 就只能支持插入了,不能支持修改。


總結

以上便是 map/set 的主要內容學習,在看的時候可以和上一章節的內容進行結合,因為 map/set 的底層的主體就是二叉搜索樹,我們可以通過對上一章節的了解來更加深刻的理解我們 map/set 的各種接口的實現。下一章節將會講解我們的 map/set 的模擬實現,我們下一章節再見。

🎇堅持到這里已經很厲害啦,辛苦啦🎇

? ? ? ? ?

づ?ど

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/98597.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/98597.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/98597.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

計算機網絡IP協議

1.TCP協議1.1 確認應答1.2 超時重傳1.3 連接管理1.4 滑動窗口1.5 流量控制1.6 擁塞控制 1.7 延時應答1.8 稍帶應答1.9 粘包問題1.10 異常情況2.IP協議 網絡層2.1 NAT機制下的幾種情況:同一個局域網中,內網ip訪問 內網 ip,可以的不同局域網中,內網IP訪問 內網IP,不行~~外網IP訪…

Windows電腦如何查看wifi連接記錄及連接時間

查詢WIFI 連接的記錄 echo netsh wlan show profiles netsh wlan show wlanreport POWERSHELL 腳本 Get-WinEvent -LogName Microsoft-Windows-WLAN-AutoConfig/Operational | Where-Object { $_.Id -in (8001,8002) } | Select-Object TimeCreated, Id, {Name"Action…

【golang學習筆記 gin 】1.2 redis 的使用

安裝redis go get -u github.com/gin-gonic/gin go get -u github.com/go-redis/redis/v8創建相關目錄 gotest->conifg->database.go->redis.go->controller ->index.go->model->user.go->router->router.gomain.go 封裝Redis package config impor…

Java學習之——“IO流“的進階流之序列化流的學習

一、核心概念&#xff1a;什么是序列化與反序列化&#xff1f;序列化 (Serialization)&#xff1a; 將一個對象&#xff08;在內存中的狀態&#xff09;轉換成一個字節序列的過程。這個字節序列包含了對象的數據、對象的類型以及對象中存儲的屬性等信息。反序列化 (Deserializa…

機器學習04——決策樹(信息增益、信息增益率、ID3、C4.5、CART、剪枝、連續值缺失值處理)

上一章&#xff1a;機器學習03——線性模型 下一章&#xff1a;機器學習05——多分類學習與類別不平衡 機器學習實戰項目&#xff1a;【從 0 到 1 落地】機器學習實操項目目錄&#xff1a;覆蓋入門到進階&#xff0c;大學生就業 / 競賽必備 文章目錄一、決策樹的基本流程&#…

(論文速讀)從語言模型到通用智能體

論文題目&#xff1a;From Multimodal LLMs to Generalist Embodied Agents: Methods and Lessons&#xff08;從多模式大型語言模型到多面手具身代理:方法和教訓&#xff09;會議&#xff1a;CVPR2025摘要&#xff1a;我們研究了多模態大型語言模型(Multimodal Large Language…

【Epiq Solutions】Matchstiq? G20 和 Matchstiq? G40 AI SDR

Matchstiq? G20 和 Matchstiq? G40 產品簡介 Matchstiq? G20 和 Matchstiq? G40 是 Epiq Solutions 推出的 緊湊型、高性能軟件定義無線電&#xff08;SDR&#xff09;平臺&#xff0c;專為滿足 嚴苛 SWaP-C&#xff08;體積、重量、功耗受限&#xff09;場景下的戰術與移動…

基于Echarts+HTML5可視化數據大屏展示-旅游智慧中心

效果展示&#xff1a; 代碼結構&#xff1a;主要代碼實現 index.html布局 <!DOCTYPE html> <html lang"en" style"font-size: 97.5px;"> <head><meta http-equiv"Content-Type" content"text/html; charsetUTF-8"…

Docker 鏡像的使用

1.鏡像的基本信息[roothost1 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu latest 802541663949 2 weeks ago 78.1MB hello-world latest 1b44b5a3e06a 4 weeks ago 10.1kB執行 docker images 命令時加上 --no…

網絡編程;套接字;TCP通訊;UDP通訊;0909

思維導圖TCP服務器端和客戶端通訊服務器端 代碼#include<myhead.h> #define SER_IP "192.168.109.12"//我的虛擬機的ip #define SER_PORT 8888 int main() {//1.創建一個用于連接的套接字文件描述符int sfd socket(AF_INET,SOCK_STREAM,0);if(sfd-1){perror(&…

貪心算法應用:柔性制造系統(FMS)刀具分配問題詳解

Java中的貪心算法應用&#xff1a;柔性制造系統(FMS)刀具分配問題詳解 1. 問題背景與定義 柔性制造系統(Flexible Manufacturing System, FMS)是現代智能制造中的關鍵組成部分&#xff0c;它能夠靈活地適應不同產品的生產需求。在FMS中&#xff0c;刀具分配是一個核心優化問題&…

不止是DELETE:MySQL多表關聯刪除的JOIN語法實戰詳解

MySQL 的 ??DELETE?? 語句用于從數據庫表中刪除記錄。這是一項非常強大且危險的操作&#xff0c;因為一旦執行&#xff0c;數據通常無法恢復。理解其語法和安全實踐至關重要。以下是 MySQL 刪除語句的詳細指南。一、 核心語法&#xff1a;DELETE??DELETE?? 語句用于刪除…

ubuntu 系統使用過程中黑屏問題分析

背景&#xff1a; 工欲善其事&#xff0c;必先利其器。作為程序員&#xff0c;想要得到更好的發展&#xff0c;遇到問題直接baidu, google 雖然可以得到一些參考或者答案&#xff0c;但是也會降低自己的思考能力&#xff0c;本文以ubuntu 使用過程中黑屏這一問題為背景&#x…

Redis(45)哨兵模式與集群模式有何區別?

Redis 提供了兩種高可用性解決方案&#xff1a;哨兵模式和集群模式。它們各自有不同的特點和適用場景。以下是詳細的對比和結合代碼的示例&#xff1a; 哨兵模式&#xff08;Sentinel&#xff09; 特點高可用性&#xff1a; Sentinel 通過監控、通知、故障轉移等功能&#xff0…

微信小程序如何進行分包處理?

目錄 分包是什么&#xff1f; 為什么要分包&#xff1f; 分包前后結構對比 具體操作步驟 第 1 步&#xff1a;規劃分包結構 第 2 步&#xff1a;修改 app.json 進行配置 第 3 步&#xff1a;創建分包目錄并移動文件 第 4 步&#xff1a;處理組件和工具函數的引用 第 5…

Go語言極速入門與精要指南從零到精通的系統化學習路徑

&#x1f49d;&#x1f49d;&#x1f49d;歡迎蒞臨我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里可以感受到一份輕松愉快的氛圍&#xff0c;不僅可以獲得有趣的內容和知識&#xff0c;也可以暢所欲言、分享您的想法和見解。 持續學習&#xff0c;不斷…

git 切換倉庫后清理分支緩存

我明白了&#xff0c;從您的截圖可以看到遠程倉庫中有 feature/v1.4_20250903 分支&#xff0c;但本地 git branch -r 看不到&#xff0c;這是因為之前更換過倉庫地址后需要重新獲取遠程倉庫的所有信息。讓我們執行以下步驟來解決這個問題&#xff1a; 首先執行 git fetch --al…

考研倒計時101天---路由選擇協議

路由選擇協議&#xff1a;RIP 與 OSPFRIP 協議&#xff08;基于距離向量算法&#xff09;RIP&#xff08;Routing Information Protocol&#xff09;是一種內部網關協議&#xff08;IGP&#xff09;&#xff0c;采用距離向量算法進行路由選擇。其主要特點如下&#xff1a;工作機…

「類 vs 實例」對比 ,「類 - 原型 - 實例」的關系

堅持的本身就是意義 目錄直觀類比類 (Class) vs 實例 (Instance)對比表示例代碼類 - 原型 - 實例關系圖解釋&#xff1a;類 (class Person)原型 (Person.prototype)實例 (new Person(...))總結&#xff1a;直觀類比 類&#xff08;Class&#xff09; 圖紙 / 模板實例&#xf…

第一課、Cocos Creator 3.8 安裝與配置

介紹說明 本文主要介紹在windows系統中&#xff0c;安裝開發Cocos使用的軟件工具&#xff0c;主要包含&#xff1a;安裝CocosDashboard控制面板、CocosCreator3.8編輯器和腳本編輯器 VS Code 。 一、Cocos Dashboard 的安裝 說明&#xff1a;Cocos Dashboard 主要作用是能夠同…