011 数据结构_哈希

高效八叉树octree:基于hash函数的数据结构 1.基础知识八叉树octree是一种递归、轴对齐且空间分隔的数据结构,常用于计算机几何来优化碰撞检测、最邻近搜索等,且常用于3D数据的表达。一个八叉树结构,将有限的三维体数据等分为8个octants。octants也被称为nodes(节点,树结构概念中)或者cells(单元,空间概念中)。将空间分成等大小的立方体可以加速细分运算,且单元大小的存储也节省空间。一个八叉树是通过递归的将空间细分成八个子... 阅读详情

前言

本文将会向你介绍哈希概念,哈希方法,如何解决哈希冲突,以及闭散列与开散列的模拟实现

1. 哈希概念

顺序结构以及平衡树中,元素关键码与其存储位置之间没有对应的关系,因此在查找一个元素时,必须要经过关键码的多次比较。顺序查找时间复杂度为O(N),平衡树中为树的高度,即 O( l o g 2 N log_2N log2​N),搜索的效率取决于搜索过程中元素的比较次数。
理想的搜索方法:可以不经过任何比较,一次直接从表中得到要搜索的元素。
如果构造一种存储结构,通过某种函数(hashFunc)使元素的存储位置与它的关键码之间能够建立一 一映射的关系,那么在查找时通过该函数可以很快找到该元素。 当向该结构中: 插入元素根据待插入元素的关键码,以此函数计算出该元素的存储位置并按此位置进行存放搜索元素
对元素的关键码进行同样的计算,把求得的函数值当做元素的存储位置,在结构中按此位置取元素比较,若关键码相等,则搜索成功
该方式即为哈希方法,哈希方法中使用的转换函数称为哈希函数,构造出来的结构称为哈希表(Hash Table)(或者称散列表
例如:数据集合{1,7,6,4,5,9};
哈希函数设置为:hash(key) = key % size; size为存储元素底层空间总的大小。
在这里插入图片描述

2. 哈希方法

哈希方法:我们通常对关键码key进行转换来确定存储的位置,比如由字符串abc转换成一个整数作为存储的位置,这个转换的方法称为哈希方法,哈希方法中运用的函数叫做哈希函数

(1)直接定址法

ps:哈希方法是一个广义的概念,而哈希函数是哈希方法的一种具体实现。

1、直接定址法 值和位置关系唯一关系,每个值都有一个唯一位置,但是值很分散,直接定址会导致空间开很大,导致空间浪费
(此方法运用于关键字范围集中,量不大的情况,关键字和存储位置是一对一的关系,不存在哈希冲突)

在这里插入图片描述

引入哈希冲突

哈希冲突概念:不同关键字通过相同的哈希函数计算出相同的哈希存储位置(不同的值映射到相同的位置上去),这种现象被称为哈希冲突或哈希碰撞,哈希冲突的发生与哈希函数的设计有关

(2)除留余数法

主要应用于关键字可以很分散,量可以很大,关键字和存储位置是多对一的关系的情况,但是存在哈希冲突
在这里插入图片描述

3. 解决哈希冲突

(1)闭散列

概念: 闭散列又称开放定址法,指当前位置被占用(哈希冲突),开放空间里按照某种规则,找一个没有被占用的位置存储
1、线性探测
从发生冲突的位置开始,依次向后探测,直到寻找到下一个空位置为止 Hashi = hashi + i(i>=0)
2、二次探测
探测公式发生变化 hashi + i^2(i>=0)

(2)开散列

开散列法又叫链地址法(开链法),首先对关键码集合用散列函数计算散列地址,具有相同地
址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中。
如图可观察到,val值为44的节点和节点val值为4的节点发生哈希冲突
开散列中每个桶中放大都是发生哈希冲突的元素

在这里插入图片描述

引入负载因子

负载因子:存储个数/空间的大小(注意这里的空间的大小是size而不是capacity)
由于在哈希表中,operator[]操作会根据已有的元素数量(即size())进行检查。因此,在计算负载因子时,要使用已有元素的个数除以哈希表的大小(即size())
size()函数返回的是当前哈希表中实际存储的元素数量,而capacity()函数返回的是哈希表的容量(即内部存储空间的大小)
负载因子:存储关键字个数/空间大小 负载因子太大,冲突可能会剧增,冲突增加,效率降低 负载因子太小,冲突降低,但是空间利用率就低了

5. 哈希表扩容

扩容的核心是先开辟新空间,然后遍历旧空间的数据,按照hashi = hashi % Newsize重新建立映射,然后将旧空间的数据拷贝到新空间去,最后交换新旧哈希表,本质上我们还是要对旧哈希表进行扩容,因此最后要swap交换两表
在这里插入图片描述

6. 哈希表插入

三种状态EMPTY、EXIST、DELETE

EMPTY,表示该位置为空。
EXIST,表示该位置被占用了。
DELETE,表示该位置被删除了。

删除状态存在的含义

或许你会有疑问:删除为什么不能直接设为空状态,而是将被删除的状态设置为DELETE

在这里插入图片描述

7. 闭散列模拟实现

数据结构

struct Elem
{
	pair<K, V> _val;
	State _state = EMPTY;
};
vector<Elem<K, V>> _ht;

在这里插入图片描述

闭散列插入

闭散列的插入步骤是:判断是否存在,判断是否需要扩容(结合负载因子),遍历旧空间拷贝数据
关于闭散列的模拟实现,核心步骤在上文都有讲,这里就不再多作赘述,具体可看下面的代码与注释

namespace Close_Hash
{
	template<class T>
	struct HashFunc
	{
		size_t operator()(const T& key)
		{
			return (size_t)key;
		}
	};

	//因为字符串做键值非常常见,库里面也特化了一份
	//BKDR算法,这里不会展开来讲
	template<>
	struct HashFunc<string>
	{
		size_t operator()(const string& key)
		{
			size_t hashi = 0;
			for (auto ch : key)
			{
				hashi = hashi * 31 + ch;
			}
			return hashi;
		}
	};

	enum State 
	{ 
		EMPTY
		,EXIST
		,DELETE
	};
	template <class K, class V>
	struct Elem
	{
		pair<K, V> _val;
		State _state = EMPTY;
	};
	template<class K, class V, class Hash = HashFunc<K>>
	class HashTable
	{
	public:
		HashTable(size_t capacity = 3)
			: _ht(capacity)
			,_size(0)
			, _totalSize(0)
		{
			for (size_t i = 0; i < capacity; ++i)
				_ht[i]._state = EMPTY;
		}

		// 插入
		bool Insert(const pair<K, V>& val)
		{
			Hash hf;
			_size = _ht.size();
			//已有
			if (Find(val.first))
			{
				return false;
			}
			else
			{
				//扩容,负载因子==0.6
				if ((double)_totalSize / _size >= 0.6)
				{
					//开辟新空间
					size_t newsize = _size * 2;
					HashTable<K, V, Hash> NewHt;
					NewHt._ht.resize(newsize);

					//遍历旧空间
					for (int i = 0; i < _size; i++)
					{
						if (_ht[i]._state == EXIST)
						{
							NewHt.Insert(_ht[i]._val);
						}
					}
					NewHt._ht.swap(_ht);
				}
				size_t hashi = hf(val.first) % _size;
				//不为空,向后查找
				while (_ht[hashi]._state == EXIST)
				{
					hashi++;
					//如果超出数组长度
					hashi %= _size;
				}
				//为空,插入
				_ht[hashi]._val.first = val.first;
				_ht[hashi]._val.second = val.second;
				_ht[hashi]._state = EXIST;
				++_totalSize;
				return true;
			}
		}

		// 查找
		Elem<K, V>* Find(const K& key)
		{
			Hash hf;
			//线性探测
			size_t hashi = hf(key) % _ht.size();
			while (_ht[hashi]._state != EMPTY)
			{	
				if (_ht[hashi]._state == EXIST 
					&& _ht[hashi]._val.first == key)
				{
					return &_ht[hashi];
				}
				hashi++;
				//超出数组长度
				hashi %= _ht.size();

			}
			//没有找到a
			return nullptr;
		}

		// 删除
		bool Erase(const K& key)
		{
			Elem<K, V>* ret = Find(key);
			//不为空就说明找到
			if (ret)
			{
				ret->_state = DELETE;
				--_totalSize;
				return true;
			}
			else return false;
		}

	private:
		size_t HashFunc(const K& key)
		{
			return key % _ht.capacity();
		}

		void CheckCapacity();
	private:
		vector<Elem<K, V>> _ht;
		size_t _size;
		size_t _totalSize;  // 哈希表中的所有元素:有效和已删除, 扩容时候要用到
	};
}

测试

		void Print()
		{
			for (int i = 0; i < _ht.size(); i++)
			{
				if (_ht[i]._state == EXIST)
				{
					//printf("[%d]->%d\n", i, _tables[i]._kv.first);
					cout << "[" << i << "]->" << _ht[i]._val.first << ":" << _ht[i]._val.second << endl;
				}
				else if (_ht[i]._state == EMPTY)
				{
					printf("[%d]->\n", i);
				}
				else
				{
					printf("[%d]->D\n", i);
				}
			}
			
void TestHT1()
{
	Close_Hash::HashTable<int, int> ht;
	int a[] = { 4,14,24,34,5,7,1 };
	for (auto e : a)
	{
		ht.Insert(make_pair(e, e));
	}
	ht.Print();
	ht.Insert(make_pair(3, 3));
	ht.Insert(make_pair(3, 3));
	ht.Insert(make_pair(-3, -3));
	ht.Print();
	cout << endl;

	ht.Erase(3);;
	ht.Print();

	if (ht.Find(3))
	{
		cout << "3存在" << endl;
	}
	else
	{
		cout << "3不存在" << endl;
	}
	ht.Insert(make_pair(23, 3));
	ht.Insert(make_pair(3, 3));
	if (ht.Find(3))
	{
		cout << "3存在" << endl;
	}
	else
	{
		cout << "3不存在" << endl;
	}
	ht.Print();
}

8. 开散列模拟实现

数据结构

	struct HashNode
	{
		HashNode* _next;
		pair<K, V> _val;
		HashNode(const pair<K, V>& val)
			:_next(nullptr)
			,_val(val)
		{}
	};
	typedef HashNode<K, V> Node;
	vector<Node*> _ht;

在这里插入图片描述

开散列插入

插入的主要逻辑是:先查找是否存在,判断是否需要扩容(依据平衡因子),开辟新空间然后遍历旧空间,将旧空间的数据拷贝到新空间上(需要根据新的映射关系,待会会细讲),最后插入节点

bool Insert(const pair<K, V>& val)
{
	Hash hf;
	//已有
	if (Find(val.first))
	{
		return false;
	}
	//扩容,负载因子==1
	if (_totalSize == _ht.size())
	{
		//开辟新空间
		size_t newsize = _ht.size() * 2;
		vector<Node*> NewHt;
		NewHt.resize(newsize);

		//遍历旧空间
		for (int i = 0; i < _ht.size(); i++)
		{
			Node* cur = _ht[i];
			while (cur)
			{
				//保存下一个结构体指针
				Node* next = cur->_next;
				size_t hashi = hf(cur->_val.first) % NewHt.size();
				//将新空间上hashi位置处的哈希桶链接到需要处理的当前节点
				cur->_next = NewHt[hashi];
				NewHt[hashi] = cur;
				//处理旧空间上哈希桶的下一个节点
				cur = next;
			}
			//防止出现悬空指针的问题
			_ht[i] = nullptr;
		}   
		_ht.swap(NewHt);
	}
		//插入节点
		size_t hashi = hf(val.first) % _ht.size();
		Node* newnode = new Node(val);
		//头插
		newnode->_next = _ht[hashi];
		_ht[hashi] = newnode;
		++_totalSize;
		return true;
}

以下是遍历旧空间,拷贝数据的图解
在这里插入图片描述
插入过程图解
在这里插入图片描述
全部代码


namespace Open_Hash
{
	template<class T>
	struct HashFunc
	{
		size_t operator()(const T& key)
		{
			if (key >= 0)
			{
				return (size_t)key;
			}
			else
			{
				return abs(key);
			}
		}
	};

	//字符串哈希算法这里不展开讲,采用的是BKDR算法
	template<>
	struct HashFunc<string>
	{
		size_t operator()(const string& key)
		{
			size_t hashi = 0;
			for (auto ch : key)
			{
				hashi = hashi * 31 + ch;
			}
			return hashi;
		}
	};
	template <class K, class V>
	struct HashNode
	{
		HashNode* _next;
		pair<K, V> _val;
		HashNode(const pair<K, V>& val)
			:_next(nullptr)
			,_val(val)
		{}
	};

	template<class K, class V, class Hash = HashFunc<K>>
	class HashTable
	{
	public:	
		HashTable()
		{
			_ht.resize(10);
		}
		~HashTable()
		{
			for (int i = 0; i < _ht.size(); i++)
			{
				Node* cur = _ht[i];
				while (cur)
				{
					Node* next = cur->_next;
					delete cur;
					cur = next;
				}
				//将当前哈希桶置空
				_ht[i] = nullptr;
			}
		}
		typedef HashNode<K, V> Node;
		// 插入
		bool Insert(const pair<K, V>& val)
		{
			Hash hf;
			//已有
			if (Find(val.first))
			{
				return false;
			}
			//扩容,负载因子==1
			if (_totalSize == _ht.size())
			{
				//开辟新空间
				size_t newsize = _ht.size() * 2;
				vector<Node*> NewHt;
				NewHt.resize(newsize);

				//遍历旧空间
				for (int i = 0; i < _ht.size(); i++)
				{
					Node* cur = _ht[i];
					while (cur)
					{
						//保存下一个结构体指针
						Node* next = cur->_next;
						size_t hashi = hf(cur->_val.first) % NewHt.size();
						//将新空间上hashi位置处的哈希桶链接到需要处理的当前节点
						cur->_next = NewHt[hashi];
						NewHt[hashi] = cur;
						//处理旧空间上哈希桶的下一个节点
						cur = next;
					}
					//防止出现悬空指针的问题
					_ht[i] = nullptr;
				}
				_ht.swap(NewHt);
			}
				//插入节点
				size_t hashi = hf(val.first) % _ht.size();
				Node* newnode = new Node(val);
				//头插
				newnode->_next = _ht[hashi];
				_ht[hashi] = newnode;
				++_totalSize;
				return true;
		}

		//查找
		Node* Find(const K& key)
		{
			Hash hf;
			//线性探测
			size_t hashi = hf(key) % _ht.size();
			Node* cur = _ht[hashi];
			//遍历对应hashi位置处的哈希桶
			while (cur)
			{
				if (cur->_val.first == key)
				{
					return cur;
				}
				cur = cur->_next;
			}
			//没有找到
			return nullptr;
		}
		// 删除
		bool Erase(const K& key)
		{
			Hash hf;
			Node* ret = Find(key);
			size_t hashi = hf(key) % _ht.size();
			//不为空就说明找到
			if (ret)
			{
				Node* cur = _ht[hashi];
				Node* prev = nullptr;
				//遍历当前哈希桶
				while (cur)
				{
					if (cur->_val.first == key)
					{
						//判断是头删还是中间位置处的删除
						if (prev == nullptr)
						{
							_ht[hashi] = cur->_next;
						}
						else
						{
							prev->_next = cur->_next;
						}
						delete cur;
						return true;
					}
					prev = cur;
					cur = cur->_next;
				}
			}
			//未找到
			return false;
		}

	private:
			vector<Node*> _ht;
			Node* _next = nullptr;
			size_t _totalSize = 0;  // 哈希表中的所有元素:有效和已删除, 扩容时候要用到
	};
}

测试

		//打印
		void Print1()
		{
			for (int i = 0; i < _ht.size(); i++)
			{
				Node* cur = _ht[i];
				cout << "[" << i << "]:";
				//哈希桶不为空
				while(cur)
				{
					cout << "(" << cur->_val.first << "," << cur->_val.second << ")" << "->";
					cur = cur->_next;
				}
				cout << endl;
			}
			cout << endl;
		}

		void Print2()
		{
			for (int i = 0; i < _ht.size(); i++)
			{
				Node* cur = _ht[i];
				//哈希桶不为空
				while (cur)
				{
					cout << cur->_val.first << ":"<< cur->_val.second << " ";
					cur = cur->_next;
				}
			}
			cout << endl;
		}
//测试
		void TestHT1()
		{
			HashTable<int, int> ht;
			int a[] = { 4,14,24,34,5,7,1 };
			for (auto e : a)
			{
				ht.Insert(make_pair(e, e));
			}

			ht.Insert(make_pair(3, 3));
			ht.Insert(make_pair(3, 3));
			ht.Insert(make_pair(-3, -3));
			ht.Print1();

			ht.Erase(3);
			ht.Print1();

			if (ht.Find(3))
			{
				cout << "3存在" << endl;
			}
			else
			{
				cout << "3不存在" << endl;
			}

			ht.Insert(make_pair(3, 3));
			ht.Insert(make_pair(23, 3));
			//ht.Insert(make_pair(-9, -9));
			ht.Insert(make_pair(-1, -1));
			ht.Print1();
		}

		void TestHT2()
		{
			string arr[] = { "香蕉", "甜瓜","苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
			//HashTable<string, int, HashFuncString> ht;
			HashTable<string, int> ht;
			for (auto& e : arr)
			{
				//auto ret = ht.Find(e);
				HashNode<string, int>* ret = ht.Find(e);
				if (ret)
				{
					ret->_val.second++;
				}
				else
				{
					ht.Insert(make_pair(e, 1));
				}
			}

			ht.Print2();

			ht.Insert(make_pair("apple", 1));
			ht.Insert(make_pair("sort", 1));

			ht.Insert(make_pair("abc", 1));
			ht.Insert(make_pair("acb", 1));
			ht.Insert(make_pair("aad", 1));

			ht.Print2();
		}

		void Some()
		{
				const size_t N = 100;
				vector<int> v;
				v.reserve(N);
				srand(time(0));
				for (size_t i = 0; i < N; ++i)
				{
					//v.push_back(rand()); // N比较大时,重复值比较多
					v.push_back(rand()%100+i); // 重复值相对少
					//v.push_back(i); // 没有重复,有序
				}
				HashTable<int, int> ht;
				for (auto e : v)
				{
					ht.Insert(make_pair(e, e));
				}
				ht.Print1();
		}

小结

今日的分享就到这里啦,后续将会向你带来位图与布隆过滤器的知识,如果本文存在疏漏或错误的地方还请您能够指出,另外如果你存在疑问,也可以评论留言哦!

小码哥《恋上数据结构与算法》笔记(十五):哈希表(Hash Table)、哈希函数、哈希冲突、HashCode和Equals方法详解 目录 具体代码在 : RBTree, 欢迎star 一、哈希表(Hash Table) 1、概念 2、哈希冲突 3、JDK1.8的哈希冲突解决方案 4、哈希函数 5、如何生成hash_code(key) 5.1、整数的哈希值 5.2、浮点数的哈希值 5.2、Long和Double的哈希值 5.3、字符串的哈希值 5.4、自定义对象的哈希值 5.5、自定义对象存储举例 6、hashCode和equals方法 (重点) 2.2.4 添加-修复性质4-上溢-RR 2.2.5 添加-修复性质4-上 阅读详情

相关推荐

树莓派国内镜像源一键配置指南

本文提供树莓派国内镜像源一键配置指南,解决默认国外源访问缓慢问题。通过自动检测系统版本并支持清华、阿里云、中科大等主流镜像站选择,大幅提升软件更新与安装速度。包含详细的手动配置方法和常见问题排查,帮助用户快速完成树莓派换源优化。

tequila的博客 1376

LCR 011

将含有相同个数0和1的问题转化为子数组和的问题,当将0转换为-1时,含有相同个数0和1的子数组sum固定为0,因此只需使用 LCR 010 的“前缀和+哈希表”解法即可解决。:前缀和 + 哈希表优化。

yang_brother的博客 311

ENVI哨兵一号数据处理

使用ENVI+SarScape处理哨兵数据

Rjjjjj11的博客 2万+

【哈希表:哈希函数构造方法、哈希冲突的处理】

常见的哈希函数的构造方法、哈希冲突的处理

阿年的博客 2855

优化QT QML中RTSP流播放延迟:海康摄像头实时监控实践

本文详细探讨了在QT QML中优化海康摄像头RTSP流播放延迟的实践方法。通过调整MediaPlayer缓冲策略、硬件加速、解码器优选等五大技巧,显著降低实时监控场景下的延迟问题。文章还提供了海康摄像头RTSP连接实战代码和避坑指南,帮助开发者快速实现高效流媒体播放。

weixin_28363123的博客 557

ctle电路求帮忙分析低中高频调节原理,搭好了电路该怎样调节参数?

🏆本文收录于专栏,主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家!持续更新中,up!up!up!!

**My Coding Family** 1129

Redis数据结构之Hash

Hash是一个String类型的field(字段)和value(值)的映射表,而且value是一个键值对集合,类似,Hash特别适合用于存储对象。每个Hash可以存储2³²-1个键值对 (40多亿)。KV键值对的结构,适合早期的购物车等场景。

Liu Zijian‘s Blog 711

人形机器人大语言模型 pi*0.6(π*0.6):最新从经验中学习的VLA

摘要:本文介绍了一种名为Recap的机器人学习方法,通过示范训练、纠错指导和强化学习三个步骤提升机器人执行复杂任务的能力。研究显示,仅依靠模仿学习的机器人难以解决错误累积问题,而Recap方法通过价值函数可视化和优势条件策略训练,使π*0.6模型在咖啡制作、纸箱组装和衣物折叠等任务中的成功率提升超过90%,吞吐量翻倍。该方法突破了传统依赖人工演示的局限,通过自主经验学习实现机器人性能的持续优化,为未来机器人基础模型的发展提供了新方向。

2506_90492529的博客 1319

hash(哈希散列) 数据结构-9

散列函数:     1、除余法 hash(key) = key % M M为素数:覆盖充分、映射均匀         缺点:1、hash(0) = 0为定点    2、相邻key的散列地址相邻 (低阶均匀)     2、MAD法         hash(key) = (a * key + b ) % M M为素数、a > 0 、b > 0、 a % m != 0         b:o

feather(猎羽) 1449

SAP 消息号T-CODE

SAP消息号修改汇总 确实有很多消息是可以修改的 FI: oBA5|oFMG|oFPM MM: oMRM|oKZZ|oMT4|oMCQ|o04C| SD: oVAH(V4)|oVM1(VL) CO:  oPR4_ACT|oPR4_CK|oPR4_CKML|oPR4_CKPF|oPR4_KKA|oPR4_KKP|oPR4_KKS| oPR4_KKS1|oPR4_P

heng0757的专栏 1万+

DirectX function “GetDeviceRemovedReason“ failed with DXGI_ERROR_DEVICE_HUNG (“The GPU will not resp

游戏报错"DXGI_ERROR_DEVICE_HUNG"的解决方案 在使用RTX 40系显卡运行FIFA 23等游戏时,可能出现DirectX报错导致游戏崩溃。这主要由于最新显卡驱动与DirectX 12的兼容性问题。解决方法包括: 降级显卡驱动版本 修改游戏配置文件,将DIRECTX_SELECT设为1 在显卡控制面板中关闭垂直同步、抗锯齿、DLSS 3等功能 调整电源模式为性能优先 这些操作可以有效解决因驱动兼容性导致的游戏崩溃问题。

猿小白的博客 3892

【哈希结构HASH相关代码附注释】

#include<stdio.h> #include<string.h> #include<malloc.h> #define _CRT_SECURE_NO_WARNINGS /* 哈希:数据和地址的一种映射关系(直接定址法) eg:LZW压缩 aababa aa == 0; ba == 1; 011 映射关系:数学中的函数关系,哈希构造函数 f(x) = x; 哈希地址:不是真正意义上的地址(指针),抽象参照地址 eg;数组中的数组下标就可以.

AltoriaPandragon的博客 470

DeepSeek赋能公文写作指南(一)

DeepSeek 的出现,为公文写作领域带来了新的曙光。作为先进的人工智能技术,DeepSeek 以其强大的语言理解与生成能力,能为公文写作提供全方位的支持。它可以快速梳理思路,提供丰富的素材参考,辅助优化语言表达,甚至能根据不同的公文类型和场景,生成极具价值的内容框架。《DeepSeek 赋能公文写作指南》正是基于此背景应运而生。本书旨在帮助公文写作者深入了解并充分利用 DeepSeek 这一强大工具,将其融入到公文写作的各个流程中。

通俗易懂学IT 5484

sas分组计数_分享 | SAS里的HASH对象

Hash对象,也叫做Hash表,是一种提高数据查询效率的数据结构。Hash表使用散列的机制存储信息。在散列机制中,键的信息用于确定唯一的值,称为哈希码。然后将哈希码用作索引,在索引位置存储与键相关的数据。散列机制的优势是操作数据的执行时间保持不变,即使是对于比较大的数据量也是如此。使用Hash对象编程是很多编程语言的一个特性,SAS也包含了这一特性。SAS内置了两种与Hash有关的对象:...

weixin_39907289的博客 1139

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

哈希表(散列表)之乘法哈希(散列)法

乘法哈希法对应的哈希函数h(k)=(A∗kmod  2w)rsh(w−r)h(k)=(A*k\mod 2^w )rsh(w-r)h(k)=(A∗kmod2w)rsh(w−r) www为计算机的每一个字的字节长度,即计算机位数,常见的有32位和64位 AAA是一个常数,满足:AAA在二进制下的长度为www位 rrr是一个与哈希表大小有关的常数,设哈希表长度为mmm,r=⌈log⁡2m⌉r=\lceil\log_2 m\rceilr=⌈log2​m⌉ rshrshrsh是右移操作,在C++编程语言中的对应代码

RealCoder的博客 2695

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

JavaGuide-数据结构-笔记011

JavaGuide面试题博文:https://javaguide.cn/。 本文是学习笔记,如果需要面试没有时间阅读原博文,可以快速浏览笔记。 推荐深度阅读对应书籍或者知识点原文,避免碎片化学习。

weixin_45148392的博客 651

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

数据结构与算法-【算法专项】Hash算法-3(Hash & BitMap)

bitmap的缺点:1. 数据不能重复:数据只有0和1 也就是有或者没有 不知道有多个 2. 数据量少时相对于普通的hash没有优势 3. 无法处理字符串:hash冲突

yinying293的博客 641

hash table相关2

引入哈希桶的概念来实现一个哈希表 学习一下国外大牛的思路 条目创建于 2013-03-18     2999 views 感谢 参考或原文 www.cnblogs.com 服务器君一共花费 30.361 ms 进行了 4 次数据库查询,努力地为您提供了这个页面。 Chapter: 散列表(哈希表) 1. 散列表(哈希表)的定义

不给糖就捣蛋的博客 1013

java - day011 - 集合, ArrayList HashMap,HashSet, Iterator 接口, for-each 循环格式

集合 ArrayList 丑数: 能被3,5,7整除多次, ArrayList list 接口 | - ArrayList | - LinkedList ArrayList 内部封装一个数组 用数组存放数据 默认初始容量是 10, 放满后会新建1.5倍的长度的新数组 ...

weixin_30532973的博客 208

[数据结构]如何构造哈希函数_大规模

优化点具体做法性能收益哈希函数选型使用MurmurHash3/xxHash避免低效自建复合键处理混合运算组合避免字符串拼接开销寻址方式替代% size省去除法指令位运算优化乘31用(H<<5)-H实现利用移位加速分布式分片一致性哈希减少扩容迁移成本安全防护SipHash随机种子防御哈希洪水攻击在亿级数据量下,以上优化能节省数十秒的CPU计算时间。核心原则:优先使用位运算(异或、移位)替代加减法,映射槽位时用& (size-1)替代。

qq_55948352的博客 172

哈希表之链地址法

package none011哈希表2; import java.io.*; import java.util.*; //哈希表之链地址法 public class HashChainApp { /** * @param args */ public static void main(String[] args) throws IOException { // TODO

梦想巅峰 973

D. Reachable Strings(想法 哈希hash)

http://codeforces.com/problemset/problem/1320/D 题意: 给一个01串,每次询问两个子串是否可以转换。转换操作为不限次数的011与110互换。 解析: 对于一个串的0序列,再人任意次操作后,0序列的每个0的奇偶性都不会变化。所以可以hash0的奇偶性。 (直接hash[i]=hash[i-1],如果是0再变化会比较方便,不需要lowerbound了) ...

QAQ 349

Redis-数据类型-Hash

Redis-数据类型-Hash。

小丁的博客 1194

L2-011 玩转二叉树 (C++ 题解)

给定一棵二叉树的和序列,要求输出这棵树反转(镜像)后的序列。

dr0w5y的博客 609

数据结构:哈希表

package none011哈希表; import java.util.*; import java.io.*; public class HashTableApp { /** * @param args */ public static void main(String[] args) throws IOException { // TODO Auto-generated m

梦想巅峰 756
上一篇: 010 数据结构_红黑树
下一篇: 008 Linux_文件在磁盘上的管理
Fan_558
博客等级 码龄4年 771粉丝 113原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fan_558

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值