20、map和set、unordered_map、un_ordered_set的复现
一、map
1、了解
map的使用和常考面试题等等,看这篇文章
- map的
key
是有序的 ,值不可重复 。 - 插入使用
insert
的效率更高,而在"更新map的键值对时,使用 [ ]运算符效率更高 。"
注意
- map 的lower和upper那2个函数,经常用在算法里。
- 直接修改某一个键的值,用 运算符[ ]
2、map的复现
- 可以使用红黑树代码 (可以放在.h文件里,然后.h放入cpp文件中,分文件编程)。
- 直接调用红黑树 。
- 剩下的部分与之前写stack、queue等等的是一样的。
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <utility>
using namespace std;
enum class Color{BLACK,RED};
template<class Key,class Value>
class RedBlackTree{class RBNode{public:RBNode* left;RBNode* right;RBNode* parent;Key key;Value value;Color color;RBNode(const Key& key,const Value& value):left(nullptr),right(nullptr),parent(nullptr),color(Color::RED),key(key),value(value){}RBNode():left(nullptr),right(nullptr),parent(nullptr),color(Color::BLACK){}};RBNode* nil;RBNode* root;size_t size;
public:RedBlackTree():nil(new RBNode()),root(nil),size(0){}~RedBlackTree(){if(root!=nil)destroy(root);delete nil;}
private:void inorderPrint(RBNode* node){if(node!=nil){inorderPrint(node->left);cout<<node->key<<" "<<node->value<<" ";inorderPrint(node->right);}}void destroy(RBNode* node){if(node!=nil){destroy(node->left);destroy(node->right);delete node;size--;}}RBNode* searchRBNode(const Key& key){RBNode* cur = root;while(cur!=nil){if(cur->key>key){cur = cur->left;}else if(cur->key<key){cur = cur->right;}else{return cur;}}return nil;}void leftRotate(RBNode* x){RBNode* y = x->right;x->right = y->left;if(y->left!=nil){y->left->parent = x;}y->parent = x->parent;if(x->parent!=nil){if(x->parent->left==x){x->parent->left = y;}else{x->parent->right = y;}}else{root = y;}y->left =x;x->parent = y;}void rightRotate(RBNode* y){RBNode* x = y->left;y->left = x->right;if(x->right!=nil){x->right->parent = y;}x->parent = y->parent;if(y->parent!=nil){if(y->parent->right==y){y->parent->right = x;}else{y->parent->left = x;}}else{root = x;}x->right = y;y->parent = x;}RBNode* minimum(RBNode* node){while(node->left!=nil){node=node->left;}return node;}void transPlant(RBNode* u,RBNode* v){if(u->parent==nil){root = v;}else if(u->parent->left==u){u->parent->left=v;}else{u->parent->right=v;}if(v!=nil)v->parent = u->parent;}void insertFixup(RBNode* node){RBNode* parent = node->parent;RBNode* grandparent;RBNode* uncle;RBNode* tmp;while(parent!=nil&&parent->color==Color::RED){grandparent = parent->parent;if(parent->parent->left==parent){uncle = grandparent->right;}else{uncle = grandparent->left;}if(uncle->color==Color::RED){parent->color=Color::BLACK;uncle->color=Color::BLACK;grandparent->color=Color::RED;node = grandparent;parent = node->parent;grandparent=parent->parent;continue;}if(grandparent->left==parent){//Lif(parent->right==node){//RleftRotate(parent);tmp = parent;parent = node;node = parent;}rightRotate(grandparent);grandparent->color = Color::RED;parent->color = Color::BLACK;}else{//Rif(parent->left==node){//LrightRotate(parent);tmp = parent;parent = node;node = parent;}leftRotate(grandparent);grandparent->color = Color::RED;parent->color = Color::BLACK;}}root->color=Color::BLACK;}void insertRBNode(const Key& key,const Value& value){RBNode* node = new RBNode(key,value);node->left = nil;node->right = nil;node->parent = nil;if(node==nil){return ;}RBNode* cur = root;RBNode* pre = nullptr;while(cur!=nil){pre = cur;if(key>cur->key){cur = cur->right;}else if(cur->key>key){cur = cur->left;}else{delete node;return ;}}if(pre==nullptr){root = node;}else{node->parent = pre;if(pre->key>key){pre->left = node;}else{pre->right = node;}}size++;insertFixup(node);}void deleteFixup(RBNode* x){RBNode* w;while((x!=root)&&(x!=nil)&&(x->color==Color::BLACK)){if(x->parent->left == x){w = x->parent->right;if(w->color==Color::RED){w->color=Color::BLACK;x->parent->color = Color::RED;leftRotate(x->parent);w = x->parent->right;}if(w->left->color==Color::BLACK&&w->right->color==Color::BLACK){w->color = Color::RED;x = x->parent;}else{if(w->right->color==Color::BLACK){//RLw->left->color = Color::BLACK;w->color = Color::RED;w->parent->color =Color::BLACK;rightRotate(w);w = x->parent->right;}w->right->color = w->color;w->color= x->parent->color;x->parent->color = Color::BLACK;leftRotate(x->parent);x = root;}}else{w = x->parent->left;if(w->color==Color::RED){w->color=Color::BLACK;x->parent->color = Color::RED;rightRotate(x->parent);w = x->parent->left;}if(w->left->color==Color::BLACK&&w->right->color==Color::BLACK){w->color = Color::RED;x = x->parent;}else{if(w->left->color==Color::BLACK){//LRw->right->color = Color::BLACK;w->color = Color::RED;x->parent->color = Color::BLACK;leftRotate(w);w = x->parent->left;}w->left->color = w->color;w->color = x->parent->color;w->parent->color = Color::BLACK;rightRotate(x->parent);x = root;}}}if(x!=nil)x->color = Color::BLACK;}void deleteRBNode(RBNode* z){RBNode* x;//替换RBNode* y= z;//删除Color y_origin_color = y->color;if(y->left==nil){x = y->right;transPlant(y, y->right);}else if(y->right==nil){x = y->left;transPlant(y, y->left);}else{y = minimum(z->right);y_origin_color = y->color;x = y->right;if(y->parent!=z){transPlant(y, x);y->right =z->right;z->right->parent = y;}transPlant(z, y);y->left = z->left;z->left->parent = y;y->color = z->color;}if(y_origin_color==Color::BLACK){deleteFixup(x);}delete z;size--;}
public:void print(){if(root!=nil)inorderPrint(root);cout<<endl;}size_t getSize(){return size;}void clear(){if(root!=nil)destroy(root);}void remove(const Key& key){RBNode* node = searchRBNode(key);if(node==nil){return;}deleteRBNode(node);}bool empty() const {return size == 0;}void insert(const Key& key,const Value& value){insertRBNode(key,value);}Value* at(const Key& key){RBNode* node = searchRBNode(key);if(node!=nil){return &node->value;}else{return nullptr;}}
};template <typename Key, typename Value> class Map {
public:Map() : rbTree() {}void insert(const Key &key, const Value &value) { rbTree.insert(key, value); }void erase(const Key &key) { rbTree.remove(key); }size_t size() { return rbTree.getSize(); }bool empty() { return rbTree.empty(); }bool contains(const Key &key) { return rbTree.at(key) != nullptr; }Value &at(const Key &key) {Value *foundVal = rbTree.at(key);if (foundVal) {return *foundVal;} else {throw std::out_of_range("Key not found");}}Value &operator[](const Key &key) {Value *foundVal = rbTree.at(key);if (foundVal) {// 如果键存在,返回关联的值return *foundVal; // 或者,返回与找到的键关联的值} else {// 如果键不存在,插入新键值对,并返回新插入的值的引用Value defaultValue;rbTree.insert(key, defaultValue);return *rbTree.at(key);}}private:RedBlackTree<Key, Value> rbTree;
};
// main函数
int main() {Map<int, int> map;int N;std::cin >> N;getchar();std::string line;for (int i = 0; i < N; i++) {std::getline(std::cin, line);std::istringstream iss(line);std::string command;iss >> command;int key;int value;if (command == "insert") {iss >> key >> value;map.insert(key, value);}if (command == "erase") {iss >> key;map.erase(key);}if (command == "contains") {iss >> key;if (map.contains(key)) {std::cout << "true" << std::endl;} else {std::cout << "false" << std::endl;}}if (command == "at") {iss >> key;try {std::cout << map.at(key) << std::endl;} catch (const std::out_of_range& e) {std::cout << "not exist" << std::endl;}}// size 命令if (command == "size") {std::cout << map.size() << std::endl;}// empty 命令if (command == "empty") {if (map.empty()) {std::cout << "true" << std::endl;} else {std::cout << "false" << std::endl;}}}return 0;
}
二、set
1、了解
看这篇文章就够了
2、代码
#include <cstddef>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <utility>
using namespace std;
enum class Color{BLACK,RED};
template<class Key,class Value>
class RBTree{class RBNode{public:RBNode* left;RBNode* right;RBNode* parent;Key key;Value value;Color color;RBNode(const Key& key,const Value& value):left(nullptr),right(nullptr),parent(nullptr),color(Color::RED),key(key),value(value){}RBNode():left(nullptr),right(nullptr),parent(nullptr),color(Color::BLACK){}};RBNode* nil;RBNode* root;size_t size;
public:RBTree():nil(new RBNode()),root(nil),size(0){}~RBTree(){if(root!=nil)destroy(root);delete nil;}
private:void inorderPrint(RBNode* node){if(node!=nil){inorderPrint(node->left);cout<<node->key<<" "<<node->value<<" ";inorderPrint(node->right);}}void destroy(RBNode* node){if(node!=nil){destroy(node->left);destroy(node->right);delete node;}size = 0;}RBNode* searchRBNode(const Key& key){RBNode* cur = root;while(cur!=nil){if(cur->key>key){cur = cur->left;}else if(cur->key<key){cur = cur->right;}else{return cur;}}return nil;}void leftRotate(RBNode* x){RBNode* y = x->right;x->right = y->left;if(y->left!=nil){y->left->parent = x;}y->parent = x->parent;if(x->parent!=nil){if(x->parent->left==x){x->parent->left = y;}else{x->parent->right = y;}}else{root = y;}y->left =x;x->parent = y;}void rightRotate(RBNode* y){RBNode* x = y->left;y->left = x->right;if(x->right!=nil){x->right->parent = y;}x->parent = y->parent;if(y->parent!=nil){if(y->parent->right==y){y->parent->right = x;}else{y->parent->left = x;}}else{root = x;}x->right = y;y->parent = x;}RBNode* minimum(RBNode* node){while(node->left!=nil){node=node->left;}return node;}void transPlant(RBNode* u,RBNode* v){if(u->parent==nil){root = v;}else if(u->parent->left==u){u->parent->left=v;}else{u->parent->right=v;}v->parent = u->parent;}void insertFixup(RBNode* node){RBNode* parent = node->parent;RBNode* grandparent;RBNode* uncle;RBNode* tmp;while(parent!=nil&&parent->color==Color::RED){grandparent = parent->parent;if(parent->parent->left==parent){uncle = grandparent->right;}else{uncle = grandparent->left;}if(uncle->color==Color::RED){parent->color=Color::BLACK;uncle->color=Color::BLACK;grandparent->color=Color::RED;node = grandparent;parent = node->parent;grandparent=parent->parent;continue;}if(grandparent->left==parent){//Lif(parent->right==node){//RleftRotate(parent);tmp = parent;parent = node;node = parent;}rightRotate(grandparent);grandparent->color = Color::RED;parent->color = Color::BLACK;}else{//Rif(parent->left==node){//LrightRotate(parent);tmp = parent;parent = node;node = parent;}leftRotate(grandparent);grandparent->color = Color::RED;parent->color = Color::BLACK;}}root->color=Color::BLACK;}void insertRBNode(const Key& key,const Value& value){RBNode* node = new RBNode(key,value);node->left = nil;node->right = nil;node->parent = nil;if(node==nil){return ;}RBNode* cur = root;RBNode* pre = nullptr;while(cur!=nil){pre = cur;if(key>cur->key){cur = cur->right;}else if(cur->key>key){cur = cur->left;}else{delete node;return ;}}if(pre==nullptr){root = node;}else{node->parent = pre;if(pre->key>key){pre->left = node;}else{pre->right = node;}}size++;insertFixup(node);}void deleteFixup(RBNode* x){RBNode* w;while((x!=root)&&(x->color==Color::BLACK)){if(x->parent->left == x){w = x->parent->right;if(w->color==Color::RED){w->color=Color::BLACK;x->parent->color = Color::RED;leftRotate(x->parent);w = x->parent->right;}if(w->left->color==Color::BLACK&&w->right->color==Color::BLACK){w->color = Color::RED;x = x->parent;}else{if(w->right->color==Color::BLACK){//RLw->left->color = Color::BLACK;w->color = Color::RED;w->parent->color =Color::BLACK;rightRotate(w);w = x->parent->right;}w->right->color = w->color;w->color= w->parent->color;w->parent->color = Color::BLACK;leftRotate(x->parent);x = root;}}else{w = x->parent->left;if(w->color==Color::RED){w->color=Color::BLACK;x->parent->color = Color::RED;rightRotate(x->parent);w = x->parent->left;}if(w->left->color==Color::BLACK&&w->right->color==Color::BLACK){w->color = Color::RED;x = x->parent;}else{if(w->left->color==Color::BLACK){//LRw->right->color = Color::BLACK;w->color = Color::RED;x->parent->color = Color::BLACK;rightRotate(w);w = x->parent->left;}w->left->color = w->color;w->color= w->parent->color;w->parent->color = Color::BLACK;leftRotate(x->parent);x = root;}}}x->color = Color::BLACK;}void deleteRBNode(RBNode* z){RBNode* x;//替换RBNode* y= z;//删除Color y_origin_color = y->color;if(y->left==nil){x = y->right;transPlant(y, x);}else if(y->right==nil){x = y->left;transPlant(y, x);}else{y = z->right;y = minimum(y);y_origin_color = y->color;x = y->right;if(y->parent!=z){transPlant(y, x);y->right =z->right;z->right->parent = y;}transPlant(z, y);y->left = z->left;z->left->parent = y;y->color = z->color;}if(y_origin_color==Color::BLACK){deleteFixup(x);}delete z;size--;}
public:void print(){if(root!=nil)inorderPrint(root);cout<<endl;}size_t getSize(){return size;}void clear(){if(root!=nil)destroy(root);}void remove(const Key& key){RBNode* node = searchRBNode(key);if(node==nil){return;}deleteRBNode(node);}bool empty() const {return size == 0;}void insert(const Key& key,const Value& value){insertRBNode(key,value);}Value* at(const Key& key){RBNode* node = searchRBNode(key);if(node!=nil){return &node->value;}else{return nullptr;}}
};template <typename Key>
class Set {
public:Set() : rbTree() {}void insert(const Key &key) { rbTree.insert(key, key); }void erase(const Key &key) { rbTree.remove(key); }size_t size() { return rbTree.getSize(); }bool empty() { return rbTree.empty(); }bool contains(const Key &key) { return rbTree.at(key) != nullptr; }private:RBTree<Key, Key> rbTree;
};int main() {Set<int> mySet;int N;std::cin >> N;getchar();std::string line;for (int i = 0; i < N; i++) {std::getline(std::cin, line);std::istringstream iss(line);std::string command;iss >> command;int element;if (command == "insert") {iss >> element;mySet.insert(element);}if (command == "earse") {iss >> element;mySet.erase(element);}if (command == "contains") {iss >> element;std::cout << (mySet.contains(element) ? "true" : "false") << std::endl;}if (command == "size") {std::cout << mySet.size() << std::endl;}if (command == "empty") {std::cout << (mySet.empty() ? "true" : "false") << std::endl;}}return 0;
}
三、unordered_map的理解
#include <cstddef>
#include <algorithm>
#include <cstddef>
#include <functional>
#include <iostream>
#include <list>
#include <utility>
#include <vector>
#include <sstream>
#include <string>template <typename Key, typename Value, typename Hash = std::hash<Key>>
class HashTable {class HashNode {public:Key key;Value value;// 从Key构造节点,Value使用默认构造explicit HashNode(const Key &key) : key(key), value() {}// 从Key和Value构造节点HashNode(const Key &key, const Value &value) : key(key), value(value) {}// 比较算符重载,只按照key进行比较bool operator==(const HashNode &other) const { return key == other.key; }bool operator!=(const HashNode &other) const { return key != other.key; }bool operator<(const HashNode &other) const { return key < other.key; }bool operator>(const HashNode &other) const { return key > other.key; }bool operator==(const Key &key_) const { return key == key_; }void print() const {std::cout << "key: " << key << " value: " << value << " ";}};private:using Bucket = std::list<HashNode>; // 定义桶的类型为存储键的链表std::vector<Bucket> buckets; // 存储所有桶的动态数组Hash hashFunction; // 哈希函数对象size_t tableSize; // 哈希表的大小,即桶的数量size_t numElements; // 哈希表中元素的数量float maxLoadFactor = 0.75; // 默认的最大负载因子// 计算键的哈希值,并将其映射到桶的索引size_t hash(const Key &key) const { return hashFunction(key) % tableSize; }// 当元素数量超过最大负载因子定义的容量时,增加桶的数量并重新分配所有键void rehash(size_t newSize) {std::vector<Bucket> newBuckets(newSize); // 创建新的桶数组for (Bucket &bucket : buckets) { // 遍历旧桶for (HashNode &hashNode : bucket) { // 遍历桶中的每个键size_t newIndex =hashFunction(hashNode.key) % newSize; // 为键计算新的索引newBuckets[newIndex].push_back(hashNode); // 将键添加到新桶中}}buckets = std::move(newBuckets); // 使用移动语义更新桶数组tableSize = newSize; // 更新哈希表大小}public:// 构造函数初始化哈希表HashTable(size_t size = 10, const Hash &hashFunc = Hash()): buckets(size), hashFunction(hashFunc), tableSize(size), numElements(0) {}// 插入键到哈希表中void insert(const Key &key, const Value &value) {if ((numElements + 1) > maxLoadFactor * tableSize) { // 检查是否需要重哈希rehash(tableSize * 2); // 重哈希,桶数量翻倍}size_t index = hash(key); // 计算键的索引std::list<HashNode> &bucket = buckets[index]; // 获取对应的桶// 如果键不在桶中,则添加到桶中if (std::find(bucket.begin(), bucket.end(), key) == bucket.end()) {bucket.push_back(HashNode(key, value));++numElements; // 增加元素数量}}void insertKey(const Key &key) { insert(key, Value{}); }// 从哈希表中移除键void erase(const Key &key) {size_t index = hash(key); // 计算键的索引auto &bucket = buckets[index]; // 获取对应的桶auto it = std::find(bucket.begin(), bucket.end(), key); // 查找键if (it != bucket.end()) { // 如果找到键bucket.erase(it); // 从桶中移除键numElements--; // 减少元素数量}}// 查找键是否存在于哈希表中Value *find(const Key &key) {size_t index = hash(key); // 计算键的索引auto &bucket = buckets[index]; // 获取对应的桶// 返回键是否在桶中auto ans = std::find(bucket.begin(), bucket.end(), key);if (ans != bucket.end()) {return &ans->value;};return nullptr;}// 获取哈希表中元素的数量size_t size() const { return numElements; }// 打印哈希表中的所有元素void print() const {std::cout << "HashTable elements:" << std::endl;for (size_t i = 0; i < buckets.size(); ++i) {std::cout << "Bucket " << i << ": ";for (const HashNode &element : buckets[i]) {element.print();}std::cout << std::endl;}}void clear() {this->buckets.clear();this->numElements = 0;}
};template <typename Key, typename Value> class Unordered_map {
private:HashTable<Key, Value> hashtable;public:Unordered_map() : hashtable(){};~Unordered_map() {}bool empty() const noexcept { return hashtable.size() == 0; }size_t size() const noexcept { return hashtable.size(); }void clear() noexcept { hashtable.clear(); }void insert(const Key &key, const Value &value) {hashtable.insert(key, value);}void erase(const Key &key) { hashtable.erase(key); }bool find(const Key &key) { return hashtable.find(key) != nullptr; }Value &operator[](const Key &key) {Value *ans = hashtable.find(key);if (ans != nullptr) {return *ans;}hashtable.insertKey(key);ans = hashtable.find(key);return *ans;}
};int main() {Unordered_map<int, int> map;int N;std::cin >> N;getchar();std::string line;for (int i = 0; i < N; i++) {std::getline(std::cin, line);std::istringstream iss(line);std::string command;iss >> command;int key;int value;if (command == "insert") {iss >> key >> value;map.insert(key, value);}if (command == "erase") {iss >> key;map.erase(key);}if (command == "find") {iss >> key;if (map.find(key)) {std::cout << "true" << std::endl;} else {std::cout << "false" << std::endl;}}// size 命令if (command == "size") {std::cout << map.size() << std::endl;}// empty 命令if (command == "empty") {if (map.empty()) {std::cout << "true" << std::endl;} else {std::cout << "false" << std::endl;}}}return 0;
}
四、unordered_set的理解
#include <algorithm>
#include <cstddef>
#include <functional>
#include <iostream>
#include <list>
#include <utility>
#include <vector>
#include <sstream>
#include <string>template <typename Key, typename Value, typename Hash = std::hash<Key>>
class HashTable {class HashNode {public:Key key;Value value;// 从Key构造节点,Value使用默认构造explicit HashNode(const Key &key) : key(key), value() {}// 从Key和Value构造节点HashNode(const Key &key, const Value &value) : key(key), value(value) {}// 比较算符重载,只按照key进行比较bool operator==(const HashNode &other) const { return key == other.key; }bool operator!=(const HashNode &other) const { return key != other.key; }bool operator<(const HashNode &other) const { return key < other.key; }bool operator>(const HashNode &other) const { return key > other.key; }bool operator==(const Key &key_) const { return key == key_; }void print() const {std::cout << key << " "<< value << " ";}};private:using Bucket = std::list<HashNode>; // 定义桶的类型为存储键的链表std::vector<Bucket> buckets; // 存储所有桶的动态数组Hash hashFunction; // 哈希函数对象size_t tableSize; // 哈希表的大小,即桶的数量size_t numElements; // 哈希表中元素的数量float maxLoadFactor = 0.75; // 默认的最大负载因子// 计算键的哈希值,并将其映射到桶的索引size_t hash(const Key &key) const { return hashFunction(key) % tableSize; }// 当元素数量超过最大负载因子定义的容量时,增加桶的数量并重新分配所有键void rehash(size_t newSize) {std::vector<Bucket> newBuckets(newSize); // 创建新的桶数组for (Bucket &bucket : buckets) { // 遍历旧桶for (HashNode &hashNode : bucket) { // 遍历桶中的每个键size_t newIndex =hashFunction(hashNode.key) % newSize; // 为键计算新的索引newBuckets[newIndex].push_back(hashNode); // 将键添加到新桶中}}buckets = std::move(newBuckets); // 使用移动语义更新桶数组tableSize = newSize; // 更新哈希表大小}public:// 构造函数初始化哈希表HashTable(size_t size = 10, const Hash &hashFunc = Hash()): buckets(size), hashFunction(hashFunc), tableSize(size), numElements(0) {}// 插入键到哈希表中void insert(const Key &key, const Value &value) {if ((numElements + 1) > maxLoadFactor * tableSize) { // 检查是否需要重哈希if (tableSize == 0) tableSize = 1;rehash(tableSize * 2); // 重哈希,桶数量翻倍}size_t index = hash(key); // 计算键的索引std::list<HashNode> &bucket = buckets[index]; // 获取对应的桶// 如果键不在桶中,则添加到桶中if (std::find(bucket.begin(), bucket.end(), key) == bucket.end()) {bucket.push_back(HashNode(key, value));++numElements; // 增加元素数量}}void insertKey(const Key &key) { insert(key, Value{}); }// 从哈希表中移除键void erase(const Key &key) {size_t index = hash(key); // 计算键的索引auto &bucket = buckets[index]; // 获取对应的桶auto it = std::find(bucket.begin(), bucket.end(), key); // 查找键if (it != bucket.end()) { // 如果找到键bucket.erase(it); // 从桶中移除键numElements--; // 减少元素数量}}// 查找键是否存在于哈希表中Value *find(const Key &key) {size_t index = hash(key); // 计算键的索引auto &bucket = buckets[index]; // 获取对应的桶// 返回键是否在桶中auto ans = std::find(bucket.begin(), bucket.end(), key);if (ans != bucket.end()) {return &ans->value;};return nullptr;}// 获取哈希表中元素的数量size_t size() const { return numElements; }// 打印哈希表中的所有元素void print() const {for (size_t i = 0; i < buckets.size(); ++i) {for (const HashNode &element : buckets[i]) {element.print();}std::cout << std::endl;}}void clear() {this->buckets.clear();this->numElements = 0;this->tableSize = 0;}
};template <typename Key> class Unordered_set {
public:Unordered_set() : hashtable(){};~Unordered_set() {}bool empty() const noexcept { return hashtable.size() == 0; }size_t size() const noexcept { return hashtable.size(); }void clear() noexcept { hashtable.clear(); }void insert(Key key) { hashtable.insertKey(key); }void erase(Key key) { hashtable.erase(key); }bool find(const Key &key) { return hashtable.find(key) != nullptr; }private:HashTable<Key, Key> hashtable;
};int main() {Unordered_set<int> mySet;int N;std::cin >> N;getchar();std::string line;for (int i = 0; i < N; i++) {std::getline(std::cin, line);std::istringstream iss(line);std::string command;iss >> command;int element;if (command == "insert") {iss >> element;mySet.insert(element);}if (command == "erase") {iss >> element;mySet.erase(element);}if (command == "find") {iss >> element;std::cout << (mySet.find(element) ? "true" : "false") << std::endl;}if (command == "size") {std::cout << mySet.size() << std::endl;}if (command == "empty") {std::cout << (mySet.empty() ? "true" : "false") << std::endl;}}return 0;
}
相关文章:
20、map和set、unordered_map、un_ordered_set的复现
一、map 1、了解 map的使用和常考面试题等等,看这篇文章 map的key是有序的 ,值不可重复 。插入使用 insert的效率更高,而在"更新map的键值对时,使用 [ ]运算符效率更高 。" 注意 map 的lower和upper那2个函数&#x…...
leetcode 189. 轮转数组
题目描述 代码: class Solution { public:void rotate(vector<int>& nums, int k) {int len nums.size();k k % len;reverse(nums,0,len-1);reverse(nums,0,k-1);reverse(nums,k,len-1);}void reverse(vector<int>& nums,int left,int right…...
得物0509面试手撕题目解答
题目 使用两个栈(一个无序栈和一个空栈)将无序栈中的元素转移到空栈,使其有序,不允许使用其他数据结构。 示例:输入:[3, 1, 6, 4, 2, 5],输出:[6, 5, 4, 3, 2, 1] 思路与代码 如…...
8天Python从入门到精通【itheima】-6~10
目录 7节-开发出第一个Python程序: 1.在cmd窗口写下第一个最简单的程序:Hello World!!! 9节: 1.如何卸载python: 2.报错:不是可运行的程序 编辑 3.报错:无法初始化设备PRN: 4.报错&…...
Qt —— 使用Enigma Virtual Box将Qt程序打包为独立可运行exe(附:完整打包方法且完美运行)
🔔 Qt 相关技术、疑难杂症文章合集(掌握后可自封大侠 ⓿_⓿)(记得收藏,持续更新中…) 打包结果 1、如下图,准备好Qt已打包后程序文件夹。附 Qt —— 在Windows下打包Qt应用程序(在其他Windows电脑下使用)...
大语言模型RLHF训练框架全景解析:OpenRLHF、verl、LLaMA-Factory与SWIFT深度对比
引言 随着大语言模型(LLM)参数规模突破千亿级,基于人类反馈的强化学习(RLHF)成为提升模型对齐能力的关键技术。OpenRLHF、verl、LLaMA-Factory和SWIFT作为开源社区的四大标杆框架,分别通过分布式架构、混合…...
VTK|类似CloudCompare的比例尺实现1-源码分析
文章目录 CloudCompare源码分析void ccGLWindowInterface::drawScale(const ccColor::Rgbub& color)🧩 总体功能🧠 函数逐步解析✅ 1. 断言只在正交模式下使用✅ 2. 计算显示的实际长度✅ 3. 字体和图形区域准备✅ 4. 计算比例尺图形的绘制位置✅ 5.…...
【计算机视觉】OpenCV实战项目:基于Tesseract与OpenCV的字符识别系统深度解析
基于Tesseract与OpenCV的字符识别系统深度解析 1. 项目概述2. 技术原理与算法设计2.1 图像预处理流水线1) 形态学操作2) 自适应阈值 2.2 Tesseract OCR引擎 3. 实战部署指南3.1 环境配置3.2 项目结构优化建议3.3 增强版代码实现 4. 常见问题与解决方案4.1 Tesseract路径错误4.2…...
CVE-2025-31258 macOS远程视图服务沙箱逃逸漏洞PoC已公开
苹果公司近日针对macOS系统中新披露的CVE-2025-31258漏洞发布补丁,该漏洞可能允许恶意应用程序突破沙箱限制,获取未授权的系统资源访问权限。在安全研究员Seo Hyun-gyu公开概念验证(PoC)利用代码后,该漏洞已在macOS Se…...
使用CAS操作实现乐观锁的完整指南
乐观锁是一种高效的并发控制机制,而CAS(Compare-And-Swap)是实现乐观锁的核心技术。下面我将详细介绍如何通过CAS操作实现乐观锁。 一、CAS操作原理 CAS(Compare-And-Swap)是一种原子操作,包含三个操作数: 内存位置(V)预期原值(A)新值(B) …...
java之网络编程
文章目录 网络编程概述什么是网络编程基本的通信架构CS架构BS架构 Java提供了哪些网络编程解决方案? 网络编程三要素IPIP地址IP域名(Domain Name)DNS域名解析(Domain Name System)公网IP、内网IP本机IPInetAddress类In…...
苍穹外卖--新增菜品
1.需求分析和设计 产品原型 业务规则: 菜品名称必须是唯一的 菜品必须属于某个分类下,不能单独存在 新增菜品时可以根据情况选择菜品的口味 每个菜品必须对应一张图片 接口设计: 根据类型查询分类(已完成) 文件上传 新增菜品 根据类型…...
Spark处理过程-转换算子
(一)RDD的处理过程 Spark使用Scala语言实现了RDD的API,程序开发者可以通过调用API对RDD进行操作处理。RDD的处理过程如图所示; RDD经过一系列的“转换”操作,每一次转换都会产生不同的RDD,以供给下一次“转换”操作使…...
运行Spark程序-在Spark-shell——RDD
一、基本概念 RDD(弹性分布式数据集)是 Apache Spark 的核心抽象,是 Spark 提供的最基本的数据处理单元。理解 RDD 的概念对于掌握 Spark 编程至关重要。以下是 RDD 的核心概念和特性: 1. 什么是 RDD? 定义…...
Qt应用程序启动时的一些思路:从单实例到性能优化的处理方案
程序启动时优化的价值 在桌面软件开发领域,应用程序的启动过程就像音乐的序曲,决定了用户对软件品质的第一印象。比如首次启动等待超过3秒时,会让大多数用户产生负面看法,而专业工具软件的容忍阈值甚至更低。Qt框架作为跨平台开发…...
vue3父子组件传值
父 → 子:props 父组件 <template><ChildComponent :message"parentMessage" :user"user" /> </template><script setup> import ChildComponent from ./ChildComponent.vue; const parentMessage Hello from paren…...
中国品牌日 | 以科技创新为引领,激光院“风采”品牌建设结硕果
品牌,作为企业不可或缺的隐形财富,在当今竞争激烈的市场环境中,其构建与强化已成为推动企业持续繁荣的关键基石。为了更好地保护自主研发产品,激光院激光公司于2020年3月7日正式注册“风采”商标,创建拥有自主知识产权…...
合合信息上线智能文档处理领域首批MCP服务,助力企业快速搭建Agent
随着大模型及Agent技术的飞速发展,通过大模型调用外部工具正在成为AI应用开发的新范式。然而,由于不同大模型的调用结构和参数格式各异,开发者需要分别编写工具调用逻辑,AI工具集成效率低下,MCP(Model Cont…...
佰力博科技与您探讨表面电阻的测试方法及应用领域
表面电阻测试是一种用于测量材料表面电阻值的技术,广泛应用于评估材料的导电性能、静电防护性能以及绝缘性能。 1、表面电阻的测试测试方法: 表面电阻测试通常采用平行电极法、同心圆电极法和四探针法等方法进行。其中,平行电极法通过在试样…...
【DeepSeek】判断两个 PCIe 设备是否属于**同一个 PCIe 子树
在 Linux 系统中,判断两个 PCIe 设备是否属于**同一个 PCIe 子树(Subtree)**是 P2P 通信的关键前提。以下是具体方法和步骤: 一、基本原理 两个 PCIe 设备属于同一子树的条件: 共享同一 Root Port:它们的…...
一份完整的高级前端性能优化手册
以下是一份完整的高级前端性能优化手册,涵盖核心原理、关键指标、优化策略及工具链,适合中大型项目深度优化: 高级前端性能优化手册 🚀 以用户体验为核心的极致性能实践 一、性能指标体系与度量 1. 核心性能指标 (Core Web Vitals) LCP (Largest Contentful Paint):最大…...
Leetcode 3543. Maximum Weighted K-Edge Path
Leetcode 3543. Maximum Weighted K-Edge Path 1. 解题思路2. 代码实现 题目链接:3543. Maximum Weighted K-Edge Path 1. 解题思路 这一题思路上就是一个遍历的思路,我们只需要考察每一个节点作为起点时,所有长为 k k k的线段的长度&…...
agentmain对业务的影响
前面一篇已经说了java agent技术主要有premain和agentmain两种形式,如果大部分业务已经在线上运行的话,不方便用premain的方式来实现,所以agentmain的方式是更加通用、灵活的 由于RASP是与用户业务运行在同一个jvm中的 ,所以RASP…...
【前端】【JavaScript】【总复习】四万字详解JavaScript知识体系
JavaScript 前端知识体系 📌 说明:本大纲从基础到高级、从语法到应用、从面试到实战,分层级讲解 JavaScript 的核心内容。 一、JavaScript 基础语法 1.1 基本概念 1.1.1 JavaScript 的发展史与用途 1. 发展简史 1995 年:JavaS…...
开源模型应用落地-qwen模型小试-Qwen3-8B-融合VLLM、MCP与Agent(七)
一、前言 随着Qwen3的开源与技术升级,其在企业中的落地场景正加速拓展至多个垂直领域。依托Agent智能体能力 和MCP协议的工具调用接口 ,Qwen3可深度融入企业业务流程,为企业提供从需求解析到自动化开发的全链路支持。 本篇将介绍如何实现Qwen3-8B模型集成MCP实现智能体交互。…...
【Linux学习笔记】理解一切皆文件实现原理和文件缓冲区
【Linux学习笔记】理解一切皆文件实现原理和文件缓冲区 🔥个人主页:大白的编程日记 🔥专栏:Linux学习笔记 前言 哈喽,各位小伙伴大家好!上期我们讲了重定向 今天我们讲的是理解一切皆文件实现原理和文件缓冲区。话不…...
MCP-RAG 服务器:完整设置和使用指南
在快速发展的人工智能应用时代,结合静态领域知识和实时网络信息的系统需求比以往任何时候都更加迫切。传统的检索增强生成(RAG)模型通常依赖于预先索引的数据,这限制了它们对新发展的反应能力。MCP-RAG Server通过将基于语义的向量…...
裸金属服务器 VS 传统物理机
一:首先,我们先介绍一下,什么是裸金属服务器? 1.虚拟机的外表-平台可视化 可以通过后台管理界面查看当前所使用的全部信息包括:当前系统版本、CPU、内存、硬盘等相关信息。 2.虚拟机的外表-操作自动化 同样也可以在…...
React百日学习计划-Grok3
关键点 研究表明,100天内学习React是可行的,尤其是你已有HTML、JS和CSS基础。该计划包括基础知识、hooks、状态管理、路由、样式化及综合项目,适合初学者。建议每天花2-3小时学习,结合免费教程和社区支持。 开始学习 学习React…...
Android NDK 高版本交叉编译:为何无需配置 FLAGS 和 INCLUDES
引言:NDK 交叉编译的演进 Android NDK(Native Development Kit)是开发高性能C/C代码的核心工具链,而交叉编译(在x86主机上生成ARM架构代码)一直是NDK的核心功能。过去,开发者需要手动配置大量编…...
Java详解LeetCode 热题 100(15):LeetCode 189. 轮转数组(Rotate Array)详解
文章目录 1. 题目描述2. 理解题目3. 解法一:使用额外数组3.1 思路3.2 Java代码实现3.3 代码详解3.4 复杂度分析3.5 适用场景 4. 解法二:环状替换法(原地算法)4.1 思路4.2 Java代码实现4.3 代码详解4.4 复杂度分析4.5 陷阱与注意事…...
出于PCB设计层面考虑,连排半孔需要注意哪些事项?
通过拼接作为后处理运行,用拼接联排半孔填充铜的自由区域。为了使通缝成为可能,必须在不同的层上有重叠的铜区域连接到指定的网上。铜的支持区域包括填充、多边形和动力平面。 高电流对电路板的潜在负面影响的另一个例子是电路板结构的物理失效。制造原始…...
JIT+Opcache如何配置才能达到性能最优
首先打开php.ini文件,进行配置 1、OPcache配置 ; 启用OPcache opcache.enable1; CLI环境下启用OPcache(按需配置) opcache.enable_cli0; 预加载脚本(PHP 7.4,加速常用类) ; opcache.preload/path/to/prel…...
VR和眼动控制集群机器人的方法
西安建筑科技大学信息与控制工程学院雷小康老师团队联合西北工业大学航海学院彭星光老师团队,基于虚拟现实(VR)和眼动追踪技术实现了人-集群机器人高效、灵活的交互控制。相关研究论文“基于虚拟现实和眼动的人-集群机器人交互方法” 发表于信…...
LabVIEW与PLC通讯程序S7.Net.dll
下图中展示的是 LabVIEW 环境下通过调用S7.Net.dll 组件与西门子 PLC 进行通讯的程序。LabVIEW 作为一种图形化编程语言,结合S7.Net.dll 的.NET 组件优势,在工业自动化领域中可高效实现与 PLC 的数据交互,快速构建工业监控与控制应用。相较于…...
【华为】现场配置OSPF
原创:厦门微思网络 实验目的 1、了解OSPF的运行原理 2、掌握OSPF的配置方法 实验拓扑 实验需求 1、根据实验拓扑图,完成设备的基本配置; 2、分别在R1、R2、R3上创建Loopback0接口,IP地址分别是1.1.1.1/32、2.2.2.2/32、3.3.3.…...
STM32-DMA数据转运(8)
目录 一、简介 二、存储器映像 三、DMA框图编辑 四、DMA基本结构 五、两个数据转运的实例 一、简介 直接存储器存取简称DMA(Direct Memory Access),它是一个数据转运小助手,主要用来协助CPU,完成数据转运的工作…...
课题推荐——低成本地磁导航入门,附公式推导和MATLAB例程运行演示
地磁导航利用地球磁场的自然特性,通过感知磁场变化,帮助机器人或无人设备实现定位和导航。相比于 GPS、激光雷达等导航方法,地磁导航具有以下优势: 低成本:使用地磁传感器(如电子罗盘)ÿ…...
微信小程序学习之底部导航栏
首先,我们在app.json中添加4个页面, "pages": ["pages/index/index","pages/category/category","pages/cart/cart","pages/user/user"], 其次我们把8张图片放到imaes文件夹下, 图标可…...
c++ std库中的文件操作学习笔记
1. 概述 C标准库提供了 头文件中的几个类来进行文件操作,这些类封装了底层的文件操作,提供了面向对象和类型安全的接口,使得文件读写更加便捷和高效。主要的文件流类包括: std::ifstream:用于从文件中读取数据。 st…...
多臂赌博机:探索与利用的平衡艺术
1. 引言 在机器学习领域,多臂赌博机(Multi-Armed Bandit,MAB)问题是强化学习的一个经典且基础的模型。这个名称源于赌场中的"单臂老虎机"(One-armed Bandit),因为这种赌博机器像强盗…...
分布式异步强化学习框架训练32B大模型:INTELLECT-2
INTELLECT-2 模型详解 一、模型概述 INTELLECT-2 是一个拥有 320 亿参数的语言模型,其训练采用了一种创新的方式,即通过社区贡献的分布式、无需许可的 GPU 资源进行强化学习训练。该模型基于 qwen2 架构构建,因此与 vllm 或 sglang 等流行库…...
HTML应用指南:利用POST请求获取全国京东快递服务网点位置信息
京东快递作为中国领先的智能供应链与综合物流服务提供商,自2007年成立以来,始终致力于通过技术创新与高效运营,为客户提供安全、可靠、快速的物流解决方案。京东快递依托京东集团的强大资源支持,凭借其自营仓储、干线运输、末端配送一体化的物流网络,在激烈的市场竞争中脱…...
通过POI实现对word基于书签的内容替换、删除、插入
一、基本概念 POI:即Apache POI, 它是一个开源的 Java 库,主要用于读取 Microsoft Office 文档(Word、Excel、PowerPoint 等),修改 或 生成 Office 文档内容,保存 为对应的二进制或 XML 格式&a…...
git进行版本控制时遇到Push cannot contain secrets的解决方法
git进行版本控制,push遇到Push cannot contain secrets的解决方法 最近在项目开发过程中,我遇到了一个让我头疼不已的问题。 问题的出现 一开始,我的项目远程仓库连接的是 Gitee,在开发过程中一切都很顺利,我也习惯…...
Java GUI 开发之旅:Swing 组件与布局管理的实战探索
在编程的世界里,图形用户界面(GUI)设计一直是提升用户体验的关键环节。Java 的 Swing 库为我们提供了强大的工具来构建跨平台的 GUI 应用。今天,我将通过一次实验,分享如何使用 Java Swing 开发一个功能丰富的 GUI 应用…...
OpenVLA (2) 机器人环境和环境数据
文章目录 前言1 BridgeData V21.1 概述1.2 硬件环境 2 数据集2.1 场景与结构2.2 数据结构2.2.1 images02.2.2 obs_dict.pkl2.2.3 policy_out.pkl 前言 按照笔者之前的行业经验, 数据集的整理是非常重要的, 因此笔者这里增加原文中出现的几个数据集和环境的学习 1 BridgeData V…...
【Ansible】基于windows主机,采用NTLM+HTTPS 认证部署
我们现在准备Linux centos7(Ansible控制机)和Windows(客户机)环境下的详细部署步骤: 一、Windows客户机配置 1. 准备SSL证书 1.1 生成自签名证书(测试用) 以管理员身份打开PowerShell&#…...
React19源码系列之 API(react-dom)
API之 preconnect preconnect – React 中文文档 preconnect 函数向浏览器提供一个提示,告诉它应该打开到给定服务器的连接。如果浏览器选择这样做,则可以加快从该服务器加载资源的速度。 preconnect(href) 一、使用例子 import { preconnect } fro…...
鸿蒙Next开发 获取APP缓存大小和清除缓存
1. 鸿蒙Next开发 获取APP缓存大小和清除缓存 1.1. 介绍 1.1.1. 文件系统分类 在最新的Core File Kit套件中,按文件所有者的不同。分为如下三类: (1)应用文件:文件所有者为应用,包括应用安装文件、应用…...