set和map + multiset和multimap(使用+封裝(RBTree))

set和map

  • 前言
  • 一、使用
    • 1. set
      • (1)、模板參數列表
      • (2)、常見構造
      • (3)、find和count
      • (4)、insert和erase
      • (5)、iterator
      • (6)、lower_bound和upper_bound
    • 2. multiset
    • 3. map
      • (1)、模板參數列表
      • (2)、構造
      • (3)、modifiers和operations
      • (4)、operator[]
    • 4. multimap
  • 二、封裝
    • RBTree
      • 迭代器原理
      • RBTree實現代碼
    • map
    • set
  • 三、總結

前言

本文介紹的是樹型關聯式容器。
關聯式容器:用來存儲數據,存儲的是<key, value>結構的鍵值對,在檢索時效率更高。主要有這四種:map,set,multimap,multiset。

鍵值對:用來標識具有一一對應關系的結構,該結構一般包含兩個成員變量key和value,key表示鍵值,value表示與key對應的信息。

SGI—STL中關于鍵值對的定義:

//pair底層
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){}
};

一、使用

1. set

(1)、模板參數列表

模板參數列表

(2)、常見構造

void test_constructor()
{set<int> s1;                            //無參構造int arr[] = { 10,20,30,40,50 };set<int> s2(arr, arr + 5);              //數組范圍構造set<int> s3(s2.begin(), s2.end());      //迭代器區間構造set<int> s4(s3);                        //拷貝構造
}

(3)、find和count

void test_find()
{set<int> s;s.insert(5);s.insert(10);s.insert(8);s.insert(2);//find return value: iterator(val is found)//otherwise set::end if (s.find(5) != s.end()){cout << "find:找到了" << endl;      }//count return value:1 (val is found),or 0 otherwiseif (s.count(5)){cout << "count:找到了" << endl;     }
}

(4)、insert和erase

void test_modify()
{//insert//去重+排序set<int> s;s.insert(10);s.insert(5);s.insert(6);s.insert(5);s.insert(5);s.insert(7);s.insert(2);for (auto e : s){cout << e << " ";     //2 5 6 7 10}cout << endl;//迭代器set<int>::iterator sit;pair<set<int>::iterator, bool> ret;   //接收插入返回值//pair<iterator, bool> insert(const value_type & val);        insert參數列表ret = s.insert(1);if (ret.second == true)sit = ret.first;cout << *sit << endl;    //1ret = s.insert(1);if (ret.second == false) sit = ret.first;cout << *sit << endl;    //1//iterator insert(iterator position, const value_type & val);  insert參數列表sit = s.insert(sit, 20);cout << *sit << endl;   //20//	template <class InputIterator>//void insert(InputIterator first, InputIterator last);        insert參數列表int arr[] = { 0,10,15 };            // 10 already in set, not inserteds.insert(arr, arr + 3);for (auto e : s){cout << e << " ";     //0 1 2 5 6 7 10 15 20}cout << endl;/////erase//void erase(iterator position);               erase參數列表s.erase(sit);    //*sit = 20//size_type erase(const value_type & val);     erase參數列表int e_ret = s.erase(0);cout << e_ret << endl;for (auto e : s){cout << e << " ";     //1 2 5 6 7 10 15}cout << endl;//void erase(iterator first, iterator last);   erase參數列表s.erase(s.begin(), s.end());for (auto e : s){cout << e << " ";     //empty}cout << endl;
}

(5)、iterator

void test_iteator()
{int arr[] = { 10,20,30,40,50 };set<int> s(arr, arr + 5);set<int>::iterator it = s.begin();set<int>::const_iterator cit = s.cbegin();set<int>::reverse_iterator rit = s.rbegin();set<int>::const_reverse_iterator crit = s.crbegin();while (it != s.end()){cout << *it << " ";   //10 20 30 40 50it++;}cout << endl;while (cit != s.cend()){cout << *cit << " ";   //10 20 30 40 50cit++;}cout << endl;while (rit != s.rend()){cout << *rit << " ";   //50 40 30 20 10rit++;}cout << endl;while (crit != s.crend()){cout << *crit << " ";  //50 40 30 20 10crit++;}cout << endl;
}

(6)、lower_bound和upper_bound

//iterator lower_bound(const value_type & val) const;                  lower_bound的聲明
//iterator upper_bound(const value_type & val) const;                  upper_bound的聲明
//pair<iterator, iterator> equal_range(const value_type& val) const;   equal_range的聲明
void test_bound()
{set<int> s;set<int>::iterator itlow, itup;for (size_t i = 1; i < 10; i++){s.insert(i * 10);               //10 20 30 40 50 60 70 80 90}//左閉右開[30,70)itlow = s.lower_bound(30);itup = s.upper_bound(60);cout << *itlow << endl;        //30cout << *itup << endl;         //70set<int>::iterator it = s.lower_bound(35);//   s > 35cout << *it << endl;           //40//*it = 50;     //不能修改,保護鍵值s.erase(itlow, itup);for (auto e : s){cout << e << " ";             //10 20 70 80 90}cout << endl;////equal_range - most_use multiset//pair<set<int>::const_iterator, set<int>::const_iterator> auto ret1 = s.equal_range(15);itlow = ret1.first;itup = ret1.second;//因為不存在15,所以itlow和itup是一段不存在的區間cout << *itlow << endl;      //20   cout << *itup << endl;       //20   左開右閉auto ret2 = s.equal_range(80);itlow = ret2.first;itup = ret2.second;//[80,90)cout << *itlow << endl;     //80   cout << *itup << endl;      //90auto ret = s.equal_range(90);itlow = ret.first;itup = ret.second;//程序直接崩潰,到最后了cout << *itlow << endl;   //90     cout << *itup << endl;    //end()
}

2. multiset

這里的演示就不和set一樣分開表示了,主要是multiset不去重

void test_multiset()
{//排序int arr[] = { 7, 7, 7, 3, 6, 5, 2, 3, 3, 3 };multiset<int> s(arr, arr + sizeof(arr) / sizeof(arr[0]));//不去重for (auto& e : s){cout << e << " ";}cout << endl;multiset<int>::iterator pos = s.find(3);  //返回中序遍歷的第一個3while (pos != s.end())           //find失敗返回end(){//*pos = 10;    //err  不能修改,保護鍵值cout << *pos << " ";++pos;}cout << endl;cout << s.count(3) << endl;   //4個3pair<multiset<int>::iterator, multiset<int>::iterator> ret = s.equal_range(7);multiset<int>::iterator itlow = ret.first;multiset<int>::iterator itup = ret.second;// [itlow, itup)// [7,end())  s.equal_range(7);//cout << *itlow << endl;//cout << *itup << endl;      //error   *itup沒有值// [itlow, itup)// [5,5)  s.equal_range(4); ret = s.equal_range(4);itlow = ret.first;itup = ret.second;cout << *itlow << endl;cout << *itup << endl;       //oks.erase(itlow, itup);   //沒有進行刪除   [5, 5)for (auto e : s){cout << e << " ";}cout << endl;
}

3. map

(1)、模板參數列表

模板參數列表

(2)、構造

void test_constructor()
{map<string, string> dict;//"insert"和"插入"都分別有隱式類型轉換,const char* 轉成const string&//不能直接進行隱式類型轉換,原因:多參數pair<string, string> kv1("insert", "插入");dict.insert(kv1);dict.insert(pair<string, string>("sort", "排序"));  //匿名對象//常用// C++98dict.insert(make_pair("string", "字符串"));// C++11 多參數的構造函數隱式類型轉換dict.insert({ "string", "字符串" });   //{}會自動調用pair的構造// 隱式類型的轉換  構造+拷貝構造(優化)string str1 = "hello";pair<string, string> kv2 = { "string", "字符串" };//const pair<string, string>& kv2 = { "string", "字符串" };  引用一個臨時變量
}

(3)、modifiers和operations

void test_modifiers()
{map<string, string> dict;dict.insert(make_pair("string", "字符串"));dict.insert(make_pair("insert", "插入"));dict.insert(make_pair("success", "成功"));//key已經有了就不會插入    //pair<iterator,bool> insert (const value_type& val);  插入的參數列表pair<map<string, string>::iterator, bool> ret = dict.insert(make_pair("insert", "xxx"));if (ret.second == false) {cout << "element already existed:";cout << ret.first->first << ":" << ret.first->second << endl;}//iterator insert (iterator position, const value_type& val);                      插入的參數列表map<string, string>::iterator it = dict.begin();it = dict.insert(it, make_pair("begin", "開始"));  // max efficiency insertingcout << it->first << ":" << it->second << endl;/*template <class InputIterator>void insert(InputIterator first, InputIterator last);*/                             //插入的參數列表map<string, string> copymap;//iterator find (const key_type& k); //查找的參數列表,返回值是查找這個位置的迭代器,如果沒查找到,返回end()copymap.insert(dict.begin(), dict.find("success"));        it = dict.begin();while (it != dict.end()){//it->first = "xxx";   //error//it->second = "sss";  //ok//cout << (*it).first << ":" << (*it).second << endl;cout << it->first << ":" << it->second << endl;++it;}cout << endl;int number = dict.erase("sucess");cout << number << endl;for (const auto& e : dict){cout << e.first << ":" << e.second << endl;}
}

(4)、operator[]

注意key不存在,operator[]是插入,at是拋異常

void test_operator()
{string arr[] = { "西瓜", "西瓜", "蘋果", "西瓜", "蘋果", "蘋果", "西瓜", "蘋果", "香蕉", "蘋果", "香蕉" };map<string, int> countMap;for (const auto& e : arr){auto it = countMap.find(e);if (it == countMap.end()){countMap.insert(make_pair(e, 1));   //首次插入}else{it->second++;                       //統計次數}}//pair<map<char, int>::iterator, bool>::iterator it = this->insert(make_pair(k,mapped_type()))//(*(it.first)).secondfor (const auto& e : arr){//查找e是否存在,如果不存在進行插入,如果存在,返回valuecountMap[e]++;}for (const auto& kv : countMap){cout << kv.first << ":" << kv.second << endl;}
}

4. multimap

multimap和map的唯一不同,前者的key可以重復

二、封裝

set和map的封裝的底層結構使用的都是紅黑樹(這篇博客介紹了紅黑樹的旋轉),在STL中set底層實際存儲的數據是鍵值對< value, value >,這樣就可以調用同個紅黑樹。

RBTree

迭代器原理

紅黑樹

雙向迭代器 -> 根據紅黑樹的特征:

  1. 迭代器++,只需要判斷當前位置的右側節點的情況
  2. 迭代器- -,只需要判斷當前位置的左側節點的情況
  1. 迭代器++
  1. 右孩子不為空,訪問右子樹的最左節點(最小節點)。
  2. 右孩子為空,下一個訪問的是孩子是父親左的祖先節點。

代碼實現:

Self& operator++()
{//右不為空if (_node->_right){//右子樹的最左節點(右子樹最小節點)Node* subLeft = _node->_right;while (subLeft->_left){subLeft = subLeft->_left;}_node = subLeft;}else  //右為空{Node* cur = _node;Node* parent = cur->_parent;//父節點為空,或者當前節點不是父節點的左孩子,循環繼續while (parent && cur == parent->_right){cur = parent;parent = parent->_parent;}//parent為空的情況和找到下一個節點的情況_node = parent;}return *this;
}
  1. 迭代器–
  1. 左孩子不為空,訪問左子樹的最右節點(最大節點)。
  2. 左孩子為空,下一個訪問的是孩子是父親右的祖先節點。
Self& operator--()
{//左孩子不為空if (_node->_left){Node* subRight = _node->_left;while (subRight->_right){subRight = subRight->_right;}_node = subRight;}else  //左孩子為空{ //孩子是父親右的那個節點Node* cur = _node;Node* parent = cur->_parent;while (parent && cur == parent->_left){cur = parent;parent = parent->_parent;}//parent為空的情況和找到下一個節點的情況_node = parent;}return *this;
}

RBTree實現代碼

//節點的顏色
enum Color
{RED,BLACK
};//這里一個模板參數T就可以,這個T既是set的key,也是map的value
template<class T>
struct RBTreeNode
{RBTreeNode<T>* _left;RBTreeNode<T>* _right;RBTreeNode<T>* _parent;T _data;Color _color;RBTreeNode(const T& data):_left(nullptr), _right(nullptr), _parent(nullptr), _data(data), _color(RED){}
};//迭代器
template<class T, class Ptr, class Ref>
struct __TreeIterator
{typedef RBTreeNode<T> Node;typedef __TreeIterator<T, Ptr, Ref> Self;//無論被實例化成什么,都是普通迭代器typedef __TreeIterator<T, T*, T&> Iterator;//這個類被實列化成const迭代器時,這個函數是一個構造,支持普通迭代器構造const迭代器//這個類被實列化成普通迭代器時,這個函數是一個拷貝構造__TreeIterator(const Iterator& it):_node(it._node){}Node* _node;//節點初始化__TreeIterator(Node* node):_node(node){}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}bool operator!=(const Self& s){return _node != s._node;}Self& operator--(){if (_node->_left){Node* subRight = _node->_left;while (subRight->_right){subRight = subRight->_right;}_node = subRight;}else  { //孩子是父親右的那個節點Node* cur = _node;Node* parent = cur->_parent;while (parent && cur == parent->_left){cur = parent;parent = parent->_parent;}//parent為空的情況和找到下一個節點的情況_node = parent;}return *this;}Self& operator++(){//右不為空if (_node->_right){//右子樹的最左節點(右子樹最小節點)Node* subLeft = _node->_right;while (subLeft->_left){subLeft = subLeft->_left;}_node = subLeft;}else  //右為空{Node* cur = _node;Node* parent = cur->_parent;while (parent && cur == parent->_right){cur = parent;parent = parent->_parent;}//parent為空的情況和找到下一個節點的情況_node = parent;}return *this;}
};//set->RBTree<K, K, SetKeyOfT> _t;
//map->RBTree<K, pair<K, V>, MapKeyOfT> _t;//KeyOfT是上層傳下來的仿函數
template<class K, class T, class KeyOfT>
class RBTree
{typedef RBTreeNode<T> Node;
public:typedef __TreeIterator<T, T*, T&> iterator;typedef __TreeIterator<T, const T*, const T&> const_iterator;iterator begin(){Node* leftMin = _root;while (leftMin && leftMin->_left){leftMin = leftMin->_left;}return iterator(leftMin);}iterator end(){//區分,這里和STL源碼中的結束方式不同,return iterator(nullptr);}const_iterator begin() const{Node* leftMin = _root;while (leftMin && leftMin->_left){leftMin = leftMin->_left;}return iterator(leftMin);}const_iterator end() const{return iterator(nullptr);}//傳K的作用Node* Find(const K& key){Node* cur = _root;KeyOfT kot;while (cur){if (kot(cur->_data) < key){cur = cur->_right;}else if (kot(cur->_data) > key){cur = cur->_left;}else{return cur;}}//沒找到,返回nullptrreturn nullptr;}//注意insert的返回值是一個鍵值對pair<iterator, bool> Insert(const T& data){if (_root == nullptr){_root = new Node(data);_root->_color = BLACK;return make_pair(iterator(_root), true);}//尋找要鏈接新節點的位置Node* parent = nullptr;Node* cur = _root;KeyOfT kot;while (cur){if (kot(cur->_data) < kot(data)){parent = cur;cur = cur->_right;}else if (kot(cur->_data) > kot(data)){parent = cur;cur = cur->_left;}else{return make_pair(iterator(cur), false);}}//插入節點 + 鏈接cur = new Node(data);cur->_color = RED;//保存節點,用于返回Node* newnode = cur;if (kot(parent->_data) > kot(data)){parent->_left = cur;}else{parent->_right = cur;}cur->_parent = parent;//調整   這里parent是否為空,是為了下一次循環判斷//       如果parent->_color == BLACK也不用玩了while (parent && parent->_color == RED){Node* grandfather = parent->_parent;if (grandfather->_left == parent){Node* uncle = grandfather->_right;//u為紅if (uncle && uncle->_color == RED){parent->_color = uncle->_color = BLACK;grandfather->_color = RED;//繼續向上調整cur = grandfather;parent = cur->_parent;}else //u不存在 或 存在且為黑{if (cur == parent->_left){//      g//   p//cRotateR(grandfather);parent->_color = BLACK;grandfather->_color = RED;}else{//      g//   p//      c	RotateL(parent);RotateR(grandfather);cur->_color = BLACK;grandfather->_color = RED;}//調整完之后,就不需要繼續改變了break;}}else   //grandfather->_right == parent{Node* uncle = grandfather->_left;//u為紅if (uncle && uncle->_color == RED){parent->_color = uncle->_color = BLACK;grandfather->_color = RED;//繼續向上調整cur = grandfather;parent = cur->_parent;}else //u不存在 或 存在且為黑{if (cur == parent->_right){//g//   p//      cRotateL(grandfather);parent->_color = BLACK;grandfather->_color = RED;}else{//g//   p//c	RotateR(parent);RotateL(grandfather);cur->_color = BLACK;grandfather->_color = RED;}//調整完之后,就不需要繼續改變了break;}}}//根節點的顏色改成黑色_root->_color = BLACK;return make_pair(iterator(newnode), true);}//判斷該樹是不是紅黑樹bool IsBalance(){return _IsBalance(_root);}//計算紅黑樹的高度int Height(){return Height(_root);}private:int Height(Node* root){if (root == nullptr)return 0;int leftHeight = Height(root->_left);int rightHeight = Height(root->_right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;}bool CheckColor(Node* root, int blacknum, int benchmark){if (root == nullptr){if (blacknum != benchmark){return false;}return true;}//計算每條路徑的黑色節點if (root->_color == BLACK){++blacknum;}if (root->_color == RED && root->_parent && root->_parent->_color == RED){cout << root->_kv.first << "出現連續紅色節點" << endl;return false;}return CheckColor(root->_left, blacknum, benchmark)&& CheckColor(root->_right, blacknum, benchmark);}bool _IsBalance(Node* root){if (root == nullptr){return true;}if (root->_color != BLACK){return false;}//基準值 -->  用于比較別的路徑黑色節點個數int benchmark = 0;Node* cur = _root;while (cur){if (cur->_color == BLACK)benchmark++;cur = cur->_left;}return CheckColor(root, 0, benchmark);}//旋轉//都是二叉樹的旋轉,所以和AVLTree的旋轉一樣,只不過這里沒有平衡因子void RotateR(Node* parent){Node* cur = parent->_left;Node* curright = cur->_right;parent->_left = curright;if (curright)curright->_parent = parent;Node* ppnode = parent->_parent;cur->_right = parent;parent->_parent = cur;if (ppnode == nullptr){_root = cur;cur->_parent = nullptr;}else{if (ppnode->_left == parent){ppnode->_left = cur;}else{ppnode->_right = cur;}cur->_parent = ppnode;}}void RotateL(Node* parent){Node* cur = parent->_right;Node* curleft = cur->_left;//重新鏈接parent->_right = curleft;if (curleft)curleft->_parent = parent;cur->_left = parent;//提前保存parent->_parent,可能是根節點,也可能是子樹的根節點Node* ppnode = parent->_parent;parent->_parent = cur;if (ppnode == nullptr){_root = cur;cur->_parent = nullptr;}else{if (ppnode->_left == parent){ppnode->_left = cur;}else{ppnode->_right = cur;}cur->_parent = ppnode;}}private:Node* _root = nullptr;
};

map

namespace kpl
{template<class K, class V>class map{//RBTree仿函數的主要作用在這里,set的封裝只是跟跑struct MapKeyOfT{const K& operator()(const pair<K, V>& kv){return kv.first;}};public:typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator;typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::const_iterator const_iterator;iterator begin(){return _t.begin();}iterator end(){return _t.end();}const_iterator begin() const{return _t.begin();}const_iterator end() const{return _t.end();}V& operator[](const K& key){pair<iterator, bool> ret = insert(make_pair(key, V()));return ret.first->second;}pair<iterator, bool> insert(const pair<const K, V>& kv){return _t.Insert(kv);}private:RBTree<K, pair<const K, V>, MapKeyOfT> _t;};
}

set

namespace kpl
{template<class K>class set{//仿函數struct SetKeyOfT{const K& operator()(const K& key){return key;}};public:typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;//set只保留一個const即可const_iterator begin() const{return _t.begin();}const_iterator end() const{return _t.end();}pair<iterator, bool> insert(const K& key){//這里返回值的first的迭代器是普通迭代器,用普通迭代器接收pair<typename RBTree<K, K, SetKeyOfT>::iterator, bool> ret = _t.Insert(key);//使用普通迭代器構造一個const的迭代器,這里就體現出迭代器實現中的那個拷貝構造return pair<iterator, bool>(ret.first, ret.second);}private:RBTree<K, K, SetKeyOfT> _t;};
}

三、總結

set

  1. 插入的元素只需要value,不用鍵值對
  2. set中的元素不能重復(set可以去重)
  3. 單個元素的訪問速度比unordered_set慢
  4. 中序遍歷有序,使用其迭代器訪問也是有序
  5. 不允許修改,破壞結構

map

  1. map中的元素是鍵值對
  2. map中的key是唯一的,不能修改,但是value可以修改
  3. 中序遍歷有序,使用其迭代器訪問也是有序
  4. 支持operator[]
  5. 單個元素的訪問速度比unordered_set慢

multiset和multimap(區分set和map)
multiset的value可以重復,multimap的key也可以重復

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

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

相關文章

9.輸出國際象棋盤【2023.11.24】

1.問題描述 要求輸出國際象棋棋盤。 2.解決思路 國際象棋棋盤由64個黑白相間的格子組成&#xff0c;分為8行*8列。用i控制行&#xff0c;j控制列&#xff0c;根據ij的和的變化來控制輸出黑方格還是白方格。 3.代碼實現 #include<stdio.h> int main(){for(int i0;i&…

各操作系統之間的關系

請移步知乎&#xff1a; 操作系統UNIX、WINDOWS、LINUX、MC OS的聯系與區別 - 知乎 (zhihu.com) 移動端的android操作系統就人盡皆知啦&#xff0c;基于linux內核。 完畢。 適用領域&#xff1a; windows,macos:主要面向個人計算機市場 Linux、Windows Server:隨著互聯網的…

基于廣義正態分布算法優化概率神經網絡PNN的分類預測 - 附代碼

基于廣義正態分布算法優化概率神經網絡PNN的分類預測 - 附代碼 文章目錄 基于廣義正態分布算法優化概率神經網絡PNN的分類預測 - 附代碼1.PNN網絡概述2.變壓器故障診街系統相關背景2.1 模型建立 3.基于廣義正態分布優化的PNN網絡5.測試結果6.參考文獻7.Matlab代碼 摘要&#xf…

網絡安全—自學

1.網絡安全是什么 網絡安全可以基于攻擊和防御視角來分類&#xff0c;我們經常聽到的 “紅隊”、“滲透測試” 等就是研究攻擊技術&#xff0c;而“藍隊”、“安全運營”、“安全運維”則研究防御技術。 2.網絡安全市場 一、是市場需求量高&#xff1b; 二、則是發展相對成熟…

深度學習之基于Pytorch照片圖像轉漫畫風格網絡系統

歡迎大家點贊、收藏、關注、評論啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代碼。 文章目錄 一項目簡介 二、功能三、系統四. 總結 一項目簡介 以下是一個基本的設計介紹&#xff1a; 數據準備&#xff1a;收集足夠的真實照片和漫畫圖像&#xff0c;用于訓練模…

typora中的快捷鍵shift enter 和 enter的交換

1 問題&#xff1a; 我最近在用 typora 進行寫作&#xff0c;但是在合格 typora 的 markdown 編輯器很奇怪&#xff0c;它的一個回車符是兩次換行&#xff0c;而用 shfit ent 找了半天都不知道怎么解決的這個問題&#xff0c;然后我就去了這個 typora 在 github 開源的問題倉庫…

hive 報錯return code 40000 from org.apache.hadoop.hive.ql.exec.MoveTask解決思路

參考學習 https://github.com/apache/hive/blob/2b57dd27ad61e552f93817ac69313066af6562d9/ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java#L47 為啥學習error code 開發過程中遇到以下錯誤&#xff0c;大家覺得應該怎么辦&#xff1f;從哪方面入手呢&#xff1f; 1.百…

解決在Windows10或Windows11下無權限修改hosts文件

解決在Windows10或Windows11下無權限修改hosts文件&#xff0c;無法寫入內容 1、首先在開始菜單中找到這個 2、接著輸入&#xff1a; C:\Windows\System32\drivers\etc3、再次輸入以下命令行&#xff1a;notepad hosts &#xff0c;并回車&#xff1a; notepad hosts 4、然后…

DataFunSummit:2023年現代數據棧技術峰會-核心PPT資料下載

一、峰會簡介 現代數據棧&#xff08;Modern Data Stack&#xff09;是一種集合了多種技術和工具的軟件基礎設施&#xff0c;旨在更好地管理和處理數據&#xff0c;并為企業提供數據驅動的洞察和決策。包含以下幾個組件&#xff1a;數據采集、數據處理、數據存儲、數據查詢和分…

區塊鏈技術與應用 【全國職業院校技能大賽國賽題目解析】第四套區塊鏈應用后端開發

第四套區塊鏈應用后端開發 環境 : ubuntu20 fisco : 2.8.0 springboot 2.1.1 fisco-java-sdk: 2.7.2 maven 3.8.8 前言 這套后端樣題,只涉及調用fisco的系統接口,不涉及此食品溯源項目的業務接口,所以我就直接生成一個springboot項目進行完成此題目。 請提前準備好一…

Docker的項目資源參考

Docker的項目資源包括以下內容&#xff1a; Docker官方網站&#xff1a;https://www.docker.com/ Docker Hub&#xff1a;https://hub.docker.com/ Docker文檔&#xff1a;https://docs.docker.com/ Docker GitHub倉庫&#xff1a;https://github.com/docker Docker官方博客…

Unity中Shader的Standard材質解析(二)

文章目錄 前言一、我們對 Standard 的 PBR 的 GI 進行解析1、我們先創建一個PBR的.cginc文件&#xff0c;用于整理用到的函數2、然后在Standard的Shader中引用該cginc文件 二、依次整理函數到該cginc文件中我們來看一下PBR中GI的鏡面反射做了些什么 二、最終代碼.cginc代碼&…

OpenGL 繪制旋轉球(Qt)

文章目錄 一、簡介二、實現代碼三、實現效果一、簡介 這里其實就是指三個互相垂直的三個圓形,正好之前已經完成了圓形平面的繪制,那么這里就需要對之前的圓形進行一些改造,使得它們可以以任意一種姿態在OpenGL中進行繪制(添加變換矩陣)。 這里同樣對其進行封裝,具體內容如…

【教學類-06-07】20231124 (55格版)X-X之間的加法、減法、加減混合題

背景需求 在大四班里&#xff0c;預測試55格“5以內、10以內、20以內的加法題、減法題、加減混合題”的“實用性”。 由于只打印一份20以內加法減法混合題。 “這套20以內的加減法最難”&#xff0c;我詢問誰會做&#xff08;摸底幼兒的水平&#xff09; 有兩位男孩舉手想挑…

joplin筆記同步 到騰訊云S3

創建存儲桶 打開騰訊云的存儲桶列表&#xff0c;點擊“創建存儲桶”&#xff0c;輸入名稱&#xff0c;選擇地域&#xff08;建議選擇離自己較近的地域以降低訪問時延&#xff09;和訪問權限&#xff08;建議選擇“私有讀寫”&#xff09;。 s3 存儲桶&#xff1a; 存儲桶的名稱…

【經典小練習】簡單的文件加密解密

文章目錄 &#x1f339;什么是文件加密?應用場景 &#x1f6f8;案例&#x1f33a;描述&#x1f33a;代碼 &#x1f339;什么是文件加密 Java文件加密是指使用Java編程語言和相關的加密算法對文件進行加密處理。通過這種方式&#xff0c;可以將文件內容轉換為一種非常規的形式…

Halcon Solution Guide I basics(4): Blob Analysis(連通性解析)

文章目錄 文章專欄前言文章解析開頭步驟分析簡單案例進階方案 進階代碼案例crystal&#xff0c;結晶匹配需求分析 文章專欄 Halcon開發 Halcon學習 練習項目gitee倉庫 CSDN Major 博主Halcon文章推薦 前言 今天來看第三章內容&#xff0c;既然是零基礎&#xff0c;而且我還有大…

希寶貓罐頭怎么樣?專業人士告訴你口碑好的貓罐頭推薦

作為一個從業寵物營養師7年的人&#xff0c;可以說對于貓咪的食物很有研究和貓罐頭品牌選購上&#xff0c;我有自己的見解。那么希寶貓罐頭怎么樣呢&#xff1f; 希寶貓罐頭采用了先進的加工工藝&#xff0c;注重產品的包裝和密封性&#xff0c;其包裝設計簡潔時尚&#xff0c…

Java定時任務 ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor 的創建 ScheduledThreadPoolExecutor executorService new ScheduledThreadPoolExecutor(1, // 核心線程數new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d") // 線程命名規則.daemon(true) // 設置線程為…

STM32 中斷系統

單片機學習 目錄 文章目錄 前言 一、中斷系統 1.1 什么是中斷 1.2 中斷優先級 1.3 中斷嵌套 1.4 C語言中的中斷程序 二、STM32的中斷通道和中斷向量 2.1 中斷通道 2.2 嵌套向量中斷控制器NVIC 2.2.1 什么是NVIC 2.2.2 NVIC基本結構 2.2.3搶占優先級和響應優先級 2.2.4 NVIC的優…