c++哈希表-map&set (无序)

2023-11-15

简述

无序的map、set,称为unordered_map、 unordered_set。 采用迭代器遍历出来的元素是无序的, 这是因此底层实现数据结构为哈希表。

1、哈希表不同于红黑树, 哈希表它的查找效率是o(1)、一个常数的效率。
虽然红黑树是o(logn), 很高的效率, 但不及它。
2、哈希表遍历的元素是无序的, 红黑树有序的。 这也决定他们实现的容器是何性质。

关于哈希表:

      不经过任何比较,一次直接从表中得到要搜索的元素。 如果构造一种存储结构,通过某种函数(哈希函数)使元素的存储位置与它的关键码之间能够建立一一映射的关系,那么在查找时通过该函数可以很快找到该元素。

哈希函数:1、直接定址法;2、除留余数法;3、平方取中法等
下面采用方法2实现。
-插入
如果插入大于容量大小的元素14, 通过哈希函数运算后位置(下标)为4, 但是位置为4已经存放了元素。 那这个元素放到哪里呢? 这个时候就会存在哈希冲突

解决哈希冲突:

1)、闭散列(线性探测)

      解决方法:如果插入的元素发生冲突,代表它这个位置已经被占用, 我们使用线性探测找下一个空位置, 然后插入该元素, 解决哈希冲突。

我们以下面哈希冲突元素44为例:
在这里插入图片描述
       为了减少哈希冲突的元素,也为了防止插入的元素大于容量, 我们定义一个负载量因子= 元素个数 / 容量大小, 一般控制在0.7左右。

 每次插入的时候, 判断负载量大小, 如果大于0.7, 需要扩容,重新分配元素位置。
定义它有两个好处:
1、控制容量范围, 不会超出
2、当扩容后,元素重新根据哈希函数分配位置,减少哈希冲突。
举个例子: 之前容量为10, 插入元素414都是同一位置,有冲突。
扩容量为20414就不是同一位置, 一个是4,一个是14, 无冲突。

      闭散列(线性探测)的缺点
      发生哈希冲突的元素会占用其他元素的位置, 导致其他元素无法插入到正确的位置, 也变为哈希冲突元素。

情况严重的时候, 变成一个顺序表, 查找效率退为o(n)。

线性探测代码

#include<iostream>
#include<vector>

using namespace std;

enum State {
	EXIST,
	DELETE,
	EMPTY
};

template<class K, class V>
struct Node {
	pair<K, V> _value;		//存储的元素
	State _state;	
};

template<class K, class V>
class HashTable {
public:

	typedef Node<K, V> Node;

	HashTable(size_t N = 10) {
		
		//开辟的数组大小
		_table.resize(N);
		//状态滞空
		for (int i = 0; i < N; ++i) {
			_table[i]._state = EMPTY;
		}
		//存放的元素个数
		_size = 0;
	}

	//插入接口
	bool insert(const pair<K, V>& value) {

		//检查容量
		chenkCapacity();
		//得出插入位置
		int index = value.first % _table.size();
		while (_table[index]._state == EXIST) {		//如果这个位置有元素, 就往下遍历

			//插入元素有重复, 直接退出										
			if (_table[index]._value.first == value.first)
				return false;

			++index;

			//如果走到尾的话, 就需要重新开始
			if (index == _table.size()) {
				index = 0;
			}
		}
		_table[index]._value = value;
		_table[index]._state = EXIST;
		++_size;
		return true;
	}

	//检查是否超过负载因子
	void chenkCapacity() {
		//负载因子 = 插入的元素个数 / 数组大小 --> _size / _table.size()

		//标准负载因子规范为 0.7
		if (_size * 10 / _table.size() >= 7) {	//整形/的话, 不会存在小数
			//超过负载因子, 需要扩容

			size_t newsize = _table.size() * 2;
			//创建新表, 旧表中元素重复计算他们的在新表的位置进行插入
			HashTable<K, V>* newHt = new HashTable<K, V>(newsize);
			for (int i = 0; i < _table.size(); ++i) {
				if (_table[i]._state == EXIST) {
					//table中存在的元素,才会进行操作添加到新表中去
					//并且,在调用新表中的inset接口, 会保存在正确的位置
					newHt->insert(_table[i]._value);
				}
			}

			//交换 - 调用vactor中swap接口
			_table.swap(newHt->_table);
		}

	}
	
	//查找接口
	Node* find(const K& key) {

		//找到查找位置
		int index = key % _table.size();
		while (_table[index]._state != EMPTY) {
			//如果插入的位置存在元素的话, 就往后找
			if (_table[index]._state == EXIST && _table[index]._value.first == key) {
				//找到插入的元素
				return &(_table[index]);
			}
			
			++index;

			//判断index是否越界
			if (index == _table.size()) {
				index = 0;
			}
		}
		return nullptr;
	}

	//删除
	bool erase(const K& key){

		Node* node = find(key);
		if (node) {
			//这个的删除是假删除 - 不会真删除, 不然会影响后续数据的查找
			//将要删除的结点状态置为DELETE, 只要不是EMPTY就行
			node->_state = DELETE;
			--_size;
			return true;
		}
		return false;
	}
	
	//遍历
	void HashTable_taervse() {

		for (int i = 0; i < _table.size(); ++i) {
			if (_table[i]._state == EXIST) {
				cout << _table[i]._value.first  << "--->" << _table[i]._value.second << endl;
			}
		}
	}

private:
	vector<Node> _table;
	size_t _size;			//存放元素的个数
};

void testHashTable() {

	HashTable<int, int> ht(2);

	ht.insert(make_pair(1, 1));
	ht.insert(make_pair(2, 1));
	ht.insert(make_pair(17, 1));
	ht.insert(make_pair(15, 1));
	ht.insert(make_pair(12, 1));
	ht.insert(make_pair(99, 1));
	ht.insert(make_pair(4, 1));
	ht.insert(make_pair(5, 1));

	ht.HashTable_taervse();

	cout << endl;
	cout << ht.erase(1) << endl;
	cout << ht.erase(17) << endl;
	cout << ht.erase(99) << endl;

	ht.HashTable_taervse();
}

int main() {
	testHashTable();
	return 0;
}

2)、开散列(哈希桶)

      a、解决方法:数组里面存放的不再是元素本身,而是一个链表。 发生冲突的元素放到链表的后面, 解决冲突。

如下图:
在这里插入图片描述
      b、哈希桶也引入负载因子, 一般设置为1, 同理和线性探测理论一样!

      c、哈希桶如果链表长度过长(也就是冲突过多),会导致查找效率退化, 和单链表一样!

如果设计哈希桶时冲突的元素会很多, 我们可以将哈希桶里面的元素存放红黑树。
没错, 是红黑树, 众所周知红黑树有着不错的查找效率(logn)
这样一来, 查找的时候如果是冲突元素, 我就去红黑树去找, 能在树头找到更好。
最差查找效率: (logn)        最优效率: (1)

对比两种处理哈希冲突的方式, 哈希桶更为优秀, 确实如此, 在STL关联式容器
unordered_map、unordered_set等底层的数据结构都是采用哈希桶实现的。

简单使用哈希桶实现无序map、set代码

#include<iostream>
#include<vector>
#include<utility>
#include<string>

using namespace std;

//单链表结点
template<class V>
struct HashNode {

	HashNode<V>* _next;
	V _data;		

	HashNode(const V& data) {
		_data = data;
		_next= nullptr;
	}
};

//哈希函数 - 基础的模板函数
template<class K>
struct HashFun {
	int operator()(const K& key) {
		return key;
	}
};

//模板特化(全特化) - 哈希函数特化 - 处理key值为string类型
template<>
struct HashFun<string> {
	int operator()(const string& key) {

		//把string转化为int类型
		int hash = 0;
		for (const auto& ch : key) {
			hash = hash * 131 + ch;
		}
		return hash;
	}
};


//哈希桶类声明
template<class K, class V, class KeyOfValue, class HFun>
class HashBucket;
//迭代器类
template<class K, class V, class KeyOfValue, class HFun>
struct Hiterator {

	//重命名哈希桶类型
	typedef HashBucket<K, V, KeyOfValue, HFun> htable;
	//重命名结点类型
	typedef HashNode<V> Node;
	//重命名结点指针类型
	typedef Node* pNode;
	//重命名迭代器类本身
	typedef Hiterator<K, V, KeyOfValue, HFun> Self;

	//定义一个存在传入结点
	pNode _node;
	htable* _ht;

	//构造函数
	Hiterator(const pNode& node, htable* ht)
		:_node(node)
		,_ht(ht)
	{

	}
	
	//重载*
	V& operator*() {
		return _node->_data;
	}

	//重载->
	V* operator->() {
		return &(_node->_data);
	}

	//重载!=
	bool operator!=(const Self& it) {
		return _node != it._node;
	}

	//++
	Self& operator++() {

		if (_node->_next) {
			_node = _node->_next;
		}
		else {

			KeyOfValue kv;
			HFun hf;
			//找到插入的位置
			int index = hf(kv(_node->_data)) % _ht->_table.size();
		
			++index;
			if (index == _ht->_table.size()) {
				_node = _node->_next;
				return *this;
			}
			while(_ht->_table[index] == nullptr) {
				
				if (index == _ht->_table.size() - 1) {
					//该结点为最后一个结点
					break;
				}
				++index;
			}
			//找到了非空链表的头节点
			_node = _ht->_table[index];
		}
		return *this;
	}
	
};



//哈希桶类
template<class K, class V, class KeyOfValue, class HFun>
class HashBucket {

public:

	//声明迭代器类为友元类 - 这样迭代器类中就可以使用到哈希桶的私有属性vector, 
	//从而能够使用哈希桶来寻找结点位置。
	template<class K, class V, class KeyOfValue, class HFun>
	friend struct Hiterator;

	//重定义结点
	typedef HashNode<V> Node;
	//重定义结点指针
	typedef Node* pNode;
	//重定义迭代器类
	typedef Hiterator<K, V, KeyOfValue, HFun> iterator;

	//迭代器 - begin
	iterator begin() {
		/*
			begin对应哈希桶头一个带头链表首结点
		*/
		int index = 0;
		while (_table[index] == nullptr) {
			
			if (index == _table.size() - 1) {
				return iterator(_table[index], this);
			}
			++index;
		}

		return iterator(_table[index], this);
	}
	
	//迭代器 - end
	iterator end() {
		/*
			end对应的是哈希桶的最后一个头链表的尾节点 - nullptr
			因此, 这块随便用一个nullptr就行。
		*/
		int index = 0;
		while (_table[index] != nullptr) {
			++index;
		}
		return iterator(_table[index], this);
	}

	//插入接口 - 为了模拟map、set接口, V目前用map实现, 为pair类
	pair<iterator, bool> insert(const V& data) {	
		
		//检查容量
		checkCapacity();
		
		//创建仿函数对象 - 来获取准确的V值
		KeyOfValue kov;
		HFun hf;

		//获取插入位置
		int index = hf(kov(data)) % _table.size();

		pNode cur = _table[index];
		while (cur) {
			
			if (kov(cur->_data) == kov(data)) {
				//有重复元素
				return make_pair(iterator(cur, this), false);
			}
			cur = cur->_next;
		}

		//头插法
		cur = new Node(data);
		cur->_next = _table[index];
		_table[index] = cur; 

		++_size;
		return make_pair(iterator(cur, this), true);
	}

	//判断容器是否合理, 不合理需要重新构建
	void checkCapacity() {

		//负载因子 可以为 1
		if (_size == _table.size()) {
			//超过负载因子, 需要扩容

			size_t newsize = (_table.size() == 0) ? 10 : 2 * _table.size();
			//创建新表
			vector<pNode> newhashB;
			newhashB.resize(newsize);

	
			KeyOfValue kv;
			HFun hf;

			for (int i = 0; i < _table.size(); ++i) {
				pNode cur = _table[i];
				while (cur) {
					//计算新的插入位置
					int index = hf(kv(cur->_data)) % newhashB.size();
					//保存next	
					pNode next = cur->_next;
					//头插
					cur->_next = newhashB[i];
					newhashB[i] = cur;
					
					cur = next;
				}
				//旧表当前的位置元素置为空
				_table[i] = nullptr;
			}
			//交换表
			_table.swap(newhashB);			
		}
	}
		
private:
	//指针数组
	vector<pNode> _table;
	size_t _size;
};




//模拟实现map
template<class K, class V, class HFun = HashFun<K>>
class UnorderedMap {
	
	//定义仿函数
	struct MapKeyOfValue {
		const K& operator()(const pair<K, V>& value) {
			return value.first;
		}
	};
public:

	typedef typename HashBucket<K, pair<K, V>, MapKeyOfValue, HFun>::iterator iterator;

	iterator begin() {
		return _hb.begin();
	}

	iterator end() {
		return _hb.end();
	}

	V& operator[](const K& key) {
		pair<iterator, bool> ret = _hb.insert(make_pair(key, V()));
		iterator it = ret.first;
		return (*it).second;
	}

	bool insert(const pair<K, V> value) {
		return _hb.insert(value).second;
	}

private:
	HashBucket<K, pair<K, V>, MapKeyOfValue, HFun> _hb;
};

//模拟实现set
template<class K, class HFun = HashFun<K>>
class UnorderedSet {

	struct SetKeyOfValue {
		const K& operator()(const K& value) {
			return value;
		}
	};
public:
	typedef typename HashBucket<K, K, SetKeyOfValue, HFun>::iterator iterator;
	
	iterator begin() {
		return _hb.begin();
	}

	iterator end() {
		return _hb.end();
	}
	
	bool insert(const K& value) {
		return _hb.insert(value).second;
	}
private:
	HashBucket<K, K, SetKeyOfValue, HFun> _hb;
};

void test_map() {
	UnorderedMap<int, int> up;


	cout << "---test_unordered_map---" << endl;

	up.insert(make_pair(5, 1));
	up.insert(make_pair(4, 1));
	up.insert(make_pair(10, 1));
	up.insert(make_pair(2, 1));
	up.insert(make_pair(1, 1));

	up[5] = 10;
	up[44] = 44;

	//auto it = up.begin();
	for (auto it : up) {
		cout << it.first << "--->" << it.second << endl;
	}
}

void test_string_map() {

	cout << "---test key of string situation---" << endl;

	UnorderedMap<string, int> up1;

	up1.insert(make_pair("a", 1));
	up1.insert(make_pair("b", 1));
	up1.insert(make_pair("aa", 1));
	up1.insert(make_pair("bb", 1));
	up1.insert(make_pair("c", 1));

	up1["aa"] = 4;
	up1["a"] = 16;

	for (auto it : up1) {
		cout << it.first << "--->" << it.second << endl;
	}

	cout << endl;
}

void test_set() {

	cout << "---test_unordered_set---" << endl;

	UnorderedSet<int> set;

	set.insert(10);
	set.insert(9);
	set.insert(4);
	set.insert(5);
	set.insert(1);
	set.insert(9);

	for (auto it : set) {
		cout << it << endl;
	}
}


int main() {

	test_map();
	test_set();
	test_string_map();
	return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c++哈希表-map&set (无序) 的相关文章

  • 在 ruby​​ 中创建哈希数组

    我想在 ruby 中创建一个哈希数组 如下所示 arr 0 name abc mobile num 9898989898 email email protected cdn cgi l email protection arr 1 name
  • 在迭代期间更改 HashMap 键

    是否可以在迭代过程中更改同一个 HashMap 实例的键 因为地图条目集没有方法entry setKey 现在我能想到的是创建另一个 HashMap MultipartParsingResult parsingResult parseReq
  • 将键->值的哈希映射“转置”为值->键?

    假设我有一个键 gt 值对的映射 我想反转它 以便我有一个新的映射 它实际上是值 gt 键 即旧值成为新键 旧键成为新值 最好的方法是什么 我正在使用Java 哦 价值观是独一无二的 我个人会用番石榴BiMap https google g
  • 当 HashMap 或 HashSet 达到最大容量时会发生什么?

    就在几分钟前 我回答了一个关于 Java中HashMap的最大可能大小 正如我一直读到的那样 HashMap 是一种可增长的数据结构 它的大小仅受 JVM 内存大小的限制 因此我认为它的大小没有硬性限制并做出了相应的回答 这同样适用于 Ha
  • HashMap 反向排序? [复制]

    这个问题在这里已经有答案了 所以我遇到了这个方法 它能够按值对 HashMap 进行排序 public static
  • 为什么这个 HashMap.get 返回 null?

    我正在尝试创建一个Hashmap为我执行查找 但是 当我运行此测试代码时 输 出为空 我认为这与密钥存储方式的性质有关 但我并不肯定 也许这是一个类似的怪癖 就像var1 var2不等于 除非它们指向内存中的同一个对象 而您必须使用var1
  • 如果 HashMap 扩展了 AbstractMap,为什么还要实现 Map? [复制]

    这个问题在这里已经有答案了 可能的重复 Java util HashMap 为什么 HashMap 扩展 AbstractMap 并实现 Map https stackoverflow com questions 2294519 java
  • 如何使用 JSTL forEach 循环迭代 HashMap? [复制]

    这个问题在这里已经有答案了 在我的 Spring MVC 应用程序中 我从controllerServlet 返回了HashMap 现在我需要使用 JSTL 在我的 jsp 中打印它 请帮忙解决这个问题 我对这一切都是新手 尝试这个 假设我
  • HashMap 不可序列化

    HashMap with Serializable键 值应该是Serializable 但这对我不起作用 尝试了其他一些IO流 没有一个有效 有什么建议吗 测试代码 public class SimpleSerializationTest
  • 我们可以将嵌套映射作为其他映射中的键吗?

    我刚刚开始用 Java 实现数据结构 想知道我们是否可以遇到这样的情况 Map
  • Java:具有重复键的 Json 可以使用 Jackson 进行映射

    我有一个具有相同键但不同值的 json 文件 如下所示 domains A name a type a1 B name r type g1 A name b type b1 这是来自外部系统 如何转换json 到 java 映射对象并访问不
  • 将 HashMap 内容写入文件

    我有一个HashMap
  • 奇怪的 Java HashMap 行为 - 找不到匹配的对象

    当我试图在里面寻找钥匙时 我遇到了一些奇怪的行为java util HashMap 我想我错过了一些东西 代码段基本上是 HashMap
  • LinkedHashMap 排序

    正如 LinkedHashMap 的 javadoc 中所指定的 如果将键重新插入到映射中 插入顺序不会受到影响 但在运行下面的程序时 我注意到在更改访问顺序时再次插入相同的键 Map
  • Hashmap 单键保存一个类。计算密钥并检索计数器

    我正在开发一个数据库自我项目 我有一个来自以下位置的输入文件 http ir dcs gla ac uk resources test collections cran http ir dcs gla ac uk resources tes
  • Java 中是否有与 Python 的 defaultdict 等效的工具?

    在 Python 中 defaultdict类提供了一种方便的方法来创建映射key gt list of values 在下面的示例中 from collections import defaultdict d defaultdict li
  • JAXB 将 XML 元素解组到 HashMap

    我发现很多文章描述了如何将 XML 元素序列解组到 HashMap 只要它们位于 父 元素内 但是 我无法将此与直接在根元素下的子元素一起使用 选项 1 有效
  • 二和 Leetcode 解释、Hashmap、Javascript

    我只是想知道谁能一步一步解释这个解决方案的算法 我不知道哈希图是如何工作的 您能否还提供一个使用哈希图的基本示例 以便我理解该算法 谢谢你 var twoSum function nums target let hash for let i
  • Java HashMap - 深拷贝

    我只是想找出如何进行深层复制的最佳解决方案HashMap 该映射中没有对象实现Cloneable 我想找到比序列化和反序列化更好的解决方案 看一眼深度克隆 在 Google Code 上您可以找到一个库 你可以阅读它https github
  • HashSet如何不允许重复?

    我正在经历add的方法HashSet 值得一提的是 如果该集合已包含该元素 则调用将保持该集合不变并返回 false But the add方法在内部保存值HashMap public boolean add E e return map

随机推荐

  • Django2.0-redis

    redis 概述 redis是一种nosql数据库 他的数据是保存在内存中 同时redis可以定时把内存数据同步到磁盘 即可以将数据持久化 并且他比memcached支持更多的数据结构 string list列表 队列和栈 set 集合 s
  • LRU和LFU的区别

    分析 回答 LRU和LFU都是内存管理的页面置换算法 LRU 即 最近最少使用淘汰算法 Least Recently Used LRU是淘汰最长时间没有被使用的页面 LRU关键是看数据最后一次被使用到发生替换的时间长短 时间越长 数据就会被
  • 都在用 AI 生成美少女,而我却。。。

    最近 AI 画画特别的火 你能从网上看到非常多好看的图片 于是我就开始了我的安装之旅 我看到的图是这样的 这样的 还有这样的 然后我就开始了我的 AI 安装生成计划 安装环境 首先我们需要安装 Python 环境 因为这个需要显卡 我估计我
  • [C++]for 循环多个限制条件

    for int i 0 j 0 i lt 5 j lt 7 i j 那么最后判断的会是j lt 7的条件 应该写成 for int i 0 j 0 i lt 5 j lt 7 i j 转载于 https www cnblogs com dr
  • django celery简单 例子

    django celery简单 例子 https docs celeryq dev en latest django first steps with django html pip list pip install Django4 2 3
  • Oracle的基本数据类型总结

    1 字符类型 CHAR 一个定长字符串 当位数不足自动用空格填充来达到其最大长度 如非NULL的CHAR 12 总是包含12字节信息 CHAR字段最多可以存储2 000字节的信息 VARCHAR2 这是一个变长字符串 与CHAR 类型不同
  • JavaScript WebGL 三维相关概念

    引子 在 JavaScript WebGL 矩阵之后 发现在实现三维效果之前还有一些概念需要理解 就去查了下资料 按照自己的习惯整合了一下 Origin My GitHub 齐次坐标 三维坐标理论上三个分量就够了 但在看相关程序的时候 发现
  • linux spi 设备节点 读写

    本文记录spi设备节点的操作方法 SPI总线设备文件名通常为 dev spidevN P N 0 1 2 P 0 1 2 其中N表示第几路SPI总线 而P表示在该路SPI总线中使用哪个CS信号线 参考链接 http www wzaobao
  • 【深度解析→博文总结】李宏毅机器学习2023作业04Self-attention(Speaker Identification)

    文章目录 系列文章 简要说明 视频分享 作业详情 调参记录 Simple Baseline 0 66025 Medium Baseline 0 81750 Stong Baseline 0 88500 Boss Baseline 0 931
  • uni-app项目中实现录音管理器(recorderManager)

    项目场景 通过微信小程序进行录音上传到服务器端进行分析诊断 得出设备发生故障的原因 问题描述 使用uni app实现声音的采集以及回放和上传等功能 并且用户可以自定义录制时长 录制时长有上限和下限 效果展示 原因分析 uni app 官网中
  • 多案分库分表带来的问题-跨库关联查询

    比如查询在合同信息的时候要关联客户数据 由于是合同数据和客户数据是在不同的数据库 那么我们肯定不能直接使用join 的这种方式去做关联查询 我们有几种主要的解决方案 1 字段冗余 比如我们查询合同库的合同表的时候需要关联客户库的客户表 我们
  • MPQ8633性能指标测试与调测分享

    目录 基于MPQ8633A测试分析 1 开关电源的三种基本拓扑结构 1 1 buck电路的基本拓扑以及原理 2 CCM DCM BCM 概论 2 1 PWM PFM PSM三种控制方法的优缺点 2 2 DCDC BUCK各种模式 2 3 C
  • 使用easypoi模板方法导出excel

    系列文章目录 一 Java使用Apache POI导出excel 二 Apache POI 操作Excel常用方法 三 Apache poi 拆分单元格并赋值 四 使用easypoi模板方法导出excel 五 Apache poi给exce
  • Dynamics 365 多选字段

    Dynamics 365 多选字段 数据库操作 C 后台操作 JS 扩展 JS string 转 int数组 数据库操作 update tablebase set field 1 对应选项值多个逗号隔开 1 C 后台操作
  • Testng学习笔记

    TestNG设计涵盖所有类型的测试 单元 功能 端到端 集成等 它需要JDK5或更高的JDK版本 TestNG是一个开源自动化测试框架 其灵感来自JUnit和NUnit的 TestNG环境设置 配置安装 TestNG是一个Java的框架 所
  • 在浏览器地址栏输入一个网址,从敲下回车键,到页面完全加载完毕,中间都发生了什么?

    1 如果地址栏中输入的是一个域名 浏览器会先使用自己的DNS缓存进行域名解析 转为IP地址 如果缓存中不存在 则会请求使用上层DNS 操作系统的DNS 操作系统会先查询本地HOST文件 如果HOST文件中不存在则会使用网络设置的DNS进行域
  • 关于 Q值

    先从大的方面来讲 从系统 从能量的角度来讲 Q值 描述任何可储能器件的性能 比如LC振荡回路 激光谐振腔 FP标准具 即Q 系统内能量 损耗功率 可见 Q值是储能器件受 振 荡驱动力和阻尼力的矛盾作用的结果 Q值越高 表示阻尼越小 当Q值
  • unity ugui序列帧动画

    使用unity自带的动画功能 1 使用unity自带的动画功能 2 在脚本中不停切换一个UI的图片以实现动画效果 1 使用unity自带的动画功能 2 在脚本中不停切换一个UI的图片以实现动画效果 using UnityEngine usi
  • 【配电网故障重构SOP】基于二阶锥松弛的加光伏风机储能进行的配电网故障处理和重构【考虑最优潮流】(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现 1 概述 电力系统最优潮流 综合考虑电网安全性和经济
  • c++哈希表-map&set (无序)

    简述 无序的map set 称为unordered map unordered set 采用迭代器遍历出来的元素是无序的 这是因此底层实现数据结构为哈希表 1 哈希表不同于红黑树 哈希表它的查找效率是o 1 一个常数的效率 虽然红黑树是o