unordered_map,unordered_set模拟实现

目录

一 . 底层结构--哈希

1.直接定址法

2. 除留余数法 + 哈希桶

3. 一些定义 

二 . 模拟实现哈希表

1.哈希表框架

​编辑

2.插入

 3.查找 

4 . 删除

5.解决使用问题

6.完整代码

三 .实现unordered_map, unordered_set

1. 初步实现unordered_map, unordered_set

2.加上迭代器(自行理解)

 3.测试用例


一 . 底层结构--哈希

哈希思想:构造一种存储结构,通过某种函数(hashFunc)使元素的存储位置与它的关键码之间能够建立一一映射的关系,那么在查找时通过该函数可以很快找到该元素。
哈希方法构造出来的结构称为哈希表(Hash Table)(或者称散列表)

1.直接定址法

2. 除留余数法 + 哈希桶

如果数据过多,并且数据很散,直接定址法不适合。

3. 一些定义 

不同关键字(4,14,24,84)通过相同的方法(% 10)计算出相同的哈希地址,该种现象称为哈希冲突或哈希碰撞。

解决哈希冲突两种常见的方法是:闭散列和开散列

闭散列:也叫开放定址法,当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有
空位置,那么可以把key存放到冲突位置中的“下一个” 空位置中去

开散列法又叫链地址法(开链法):首先对关键码集合用散列函数计算散列地址,具有相同地
址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链
接起来,各链表的头结点存储在哈希表中。

(我们采用的是开散列法)

二 . 模拟实现哈希表

1.哈希表框架


 

代码: 

//节点
template<class K, class V>
struct HashNode
{
	HashNode(const pair<K, V>& kv)
		:_kv(kv)
		, _next(nullptr)
	{}
	pair<K, V> _kv;
	HashNode<K, V>* _next;
};

template<class K, class V>
{
    typedef HashNode<K, V> Node;
public:
	HashTable()
	{
		_tables.resize(10, nullptr);
	}
    ~HashTable()
	{
		for (size_t i = 0; i < _tables.size(); i++)
		{
			Node* cur = _tables[i];
			while (cur)
			{
				Node* next = cur->_next;
				delete cur;
				cur = next;
			}
		}
	}
    //删除
    //插入
    //查找

private:
	vector<Node*> _tables;
	size_t _n = 0; // 哈希表实际元素个数
}

_n存在的意义:判断_tables什么时候扩容。

开散列最好的情况是:每个哈希桶中刚好挂一个节点,再继续插入元素时,每一次都会发生哈希冲突,因此,在元素个数刚好等于桶的个数时,可以给哈希表增容。
 

2.插入

bool Insert(const pair<K, V>& kv)
	{
		if(Find(kv.first))
			return false;
	    //扩容
		if (_n / _tables.size() == 1)
		{
			size_t newSize = _tables.size() * 2;
			vector<Node*> newTables;
			newTables.resize(newSize, nullptr);
			for (size_t i = 0; i < _tables.size(); i++)
			{
				Node* cur = _tables[i];
				while (cur)
				{
					size_t hashi = cur->_kv.first % newTables.size();
					cur->_next = newTables[hashi];
					newTables[hashi] = cur;
				}
				_tables[i] = nullptr;
			}
			_tables.swap(newTables);
		}

		size_t hashi = kv.first % _tables.size();
		Node* newnode = new Node(kv);
		newnode->_next = _tables[hashi];
		_tables[hashi] = newnode;
		_n++;

		return false;
	}

 3.查找 

Node* Find(const K& key)
	{
		size_t hashi = key % _tables.size();//找到插入位置
		Node* cur = _tables[hashi];
		while (cur)
		{
			if (cur->_kv.first == key)
			{
				return cur;
			}
			cur = cur->_next;
		}
		return nullptr;
	}

4 . 删除

 

	bool erase(const K& key)
	{
		size_t hashi = key % _tables.size();
		Node* cur = _tables[hashi];
		Node* prev = nullptr;
		if (cur->_kv.first == key)
		{
			_tables[hashi] = nullptr;
			return true;
		}
		while (cur)
		{
			if (cur->_kv.first == key)
			{
				prev->_next = cur->_next;
				delete cur;
				return true;
			}
			prev = cur;
			cur = cur->_next;
		}
		return false;
	}

5.解决使用问题

如果kv.first为string或者其他类型,就会出问题。

解决:

template<class K>
struct HashFunc
{
	size_t operator()(const K& key)
	{
		return (size_t)key;
	}
};
template<>
struct HashFunc<string>
{
	size_t operator()(const string& key)
	{
		size_t sum = 0;
		for (auto& e : key)
		{
			sum *= 31;
			sum += e;
		}
		return sum;
	}
};

接着把所有用除留余数法的部分进行修改:

6.完整代码

#pragma once

template<class K, class V>
struct HashNode
{
	HashNode(const pair<K, V>& kv)
		:_kv(kv)
		, _next(nullptr)
	{}
	pair<K, V> _kv;
	HashNode<K, V>* _next;
};


template<class K>
struct HashFunc
{
	size_t operator()(const K& key)
	{
		return (size_t)key;
	}
};
template<>
struct HashFunc<string>
{
	size_t operator()(const string& key)
	{
		size_t sum = 0;
		for (auto& e : key)
		{
			sum *= 31;
			sum += e;
		}
		return sum;
	}
};

//哈希桶
template<class K, class V, class Hash = HashFunc<K>>
class HashTable
{
	typedef HashNode<K, V> Node;
	Hash hf;
public:
	HashTable()
	{
		_tables.resize(10, nullptr);
	}

	~HashTable()
	{
		for (size_t i = 0; i < _tables.size(); i++)
		{
			Node* cur = _tables[i];
			while (cur)
			{
				Node* next = cur->_next;
				delete cur;
				cur = next;
			}
		}
	}

	bool Insert(const pair<K, V>& kv)
	{
		if(Find(kv.first))
			return false;
	    //扩容
		if (_n / _tables.size() == 1)
		{
			size_t newSize = _tables.size() * 2;
			vector<Node*> newTables;
			newTables.resize(newSize, nullptr);
			for (size_t i = 0; i < _tables.size(); i++)
			{
				Node* cur = _tables[i];
				while (cur)
				{
					size_t hashi = hf(cur->_kv.first) % newTables.size();
					cur->_next = newTables[hashi];
					newTables[hashi] = cur;
				}
				_tables[i] = nullptr;
			}
			_tables.swap(newTables);
		}

		size_t hashi = hf(kv.first) % _tables.size();
		Node* newnode = new Node(kv);
		newnode->_next = _tables[hashi];
		_tables[hashi] = newnode;
		_n++;

		return false;
	}

	Node* Find(const K& key)
	{
		size_t hashi = hf(key) % _tables.size();
		Node* cur = _tables[hashi];
		while (cur)
		{
			if (cur->_kv.first == key)
			{
				return cur;
			}
			cur = cur->_next;
		}
		return nullptr;
	}

	bool erase(const K& key)
	{
		size_t hashi = hf(key) % _tables.size();
		Node* cur = _tables[hashi];
		Node* prev = nullptr;
		if (cur->_kv.first == key)
		{
			_tables[hashi] = nullptr;
			return true;
		}
		while (cur)
		{
			if (cur->_kv.first == key)
			{
				prev->_next = cur->_next;
				delete cur;
				return true;
			}
			prev = cur;
			cur = cur->_next;
		}
		return false;
	}

private:
	vector<Node*> _tables;
	size_t _n = 0;
};

三 .实现unordered_map, unordered_set

1. 初步实现unordered_map, unordered_set

这部分内容类似红黑树封装map,set。

unordered_set.h

#pragma once

template<class K, class Hash = HashFunc<K>>
class unordered_set
{
	struct KeyOfT
	{
		const K& operator()(const K& key)
		{
			return key;
		}
	};

public:
	bool insert(const K& key)
	{
		return _ht.Insert(key);
	}

	bool erase(const K& key)
	{
		return _ht.Erase(key);
	}

	HashNode<K>* find(const K& key)
	{
		return _ht.Find(key);
	}


private:
	HashTable<K, K, KeyOfT> _ht;
};

unordered_map.h

#pragma once

template<class K, class V, class Hash = HashFunc<K>>
class unordered_map
{
	struct KeyOfT
	{
		const K& operator()(const pair<K, V>& kv)
		{
			return kv.first;
		}
	};

public:
	bool insert(const pair<K, V>& key)
	{
		return _ht.Insert(key);
	}

	bool erase(const K& key)
	{
		return _ht.Erase(key);
	}

	HashNode<pair<K, V>>* find(const K& key)
	{
		return _ht.Find(key);
	}

private:
	HashTable<K, pair<K, V>, KeyOfT> _ht;
};

HashTable.h

#pragma once


template<class T>
struct HashNode
{
	HashNode(const T& data)
		:_data(data)
		, _next(nullptr)
	{}
	T _data;
	HashNode<T>* _next;
};


template<class K>
struct HashFunc
{
	size_t operator()(const K& key)
	{
		return (size_t)key;
	}
};
template<>
struct HashFunc<string>
{
	size_t operator()(const string& key)
	{
		size_t sum = 0;
		for (auto& e : key)
		{
			sum *= 31;
			sum += e;
		}
		return sum;
	}
};

//哈希桶
template<class K, class T, class KeyOfT>
class HashTable
{
	typedef HashNode<T> Node;
	HashFunc<K> hf;
	KeyOfT kot;
public:
	HashTable()
	{
		_tables.resize(10, nullptr);
	}

	~HashTable()
	{
		for (size_t i = 0; i < _tables.size(); i++)
		{
			Node* cur = _tables[i];
			while (cur)
			{
				Node* next = cur->_next;
				delete cur;
				cur = next;
			}
		}
	}

	bool Insert(const T& data)
	{
		if(Find(kot(data)))
			return false;
	    //扩容
		if (_n / _tables.size() == 1)
		{
			size_t newSize = _tables.size() * 2;
			vector<Node*> newTables;
			newTables.resize(newSize, nullptr);
			for (size_t i = 0; i < _tables.size(); i++)
			{
				Node* cur = _tables[i];
				while (cur)
				{
					size_t hashi = hf(kot(cur->_data)) % newTables.size();
					cur->_next = newTables[hashi];
					newTables[hashi] = cur;
				}
				_tables[i] = nullptr;
			}
			_tables.swap(newTables);
		}

		size_t hashi = hf(kot(data)) % _tables.size();
		Node* newnode = new Node(data);
		newnode->_next = _tables[hashi];
		_tables[hashi] = newnode;
		_n++;

		return false;
	}

	Node* Find(const K& key)
	{
		size_t hashi = hf(key) % _tables.size();
		Node* cur = _tables[hashi];
		while (cur)
		{
			if (kot(cur->_data) == key)
			{
				return cur;
			}
			cur = cur->_next;
		}
		return nullptr;
	}

	bool Erase(const K& key)
	{
		size_t hashi = hf(key) % _tables.size();
		Node* cur = _tables[hashi];
		Node* prev = nullptr;
		if (kot(cur->_data) == key)
		{
			_tables[hashi] = nullptr;
			return true;
		}
		while (cur)
		{
			if (kot(cur->_data) == key)
			{
				prev->_next = cur->_next;
				delete cur;
				return true;
			}
			prev = cur;
			cur = cur->_next;
		}
		return false;
	}

private:
	vector<Node*> _tables;
	size_t _n = 0;
};

2.加上迭代器(自行理解)

unordered_map.h

#pragma once

template<class K, class V, class Hash = HashFunc<K>>
class unordered_map
{
	struct KeyOfT
	{
		const K& operator()(const pair<K, V>& kv)
		{
			return kv.first;
		}
	};
public:
	typedef typename HashTable<K, pair<const K, V>, KeyOfT, Hash>::iterator iterator;

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

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

	pair<iterator, bool> insert(const pair<K, V>& kv)
	{
		return _ht.Insert(kv);
	}

	V& operator[](const K& key)
	{
		pair<iterator, bool> ret = _ht.Insert(make_pair(key, V()));
		return ret.first->second;
	}

	const V& operator[](const K& key) const
	{
		pair<iterator, bool> ret = _ht.Insert(make_pair(key, V()));
		return ret.first->second;
	}

	iterator find(const K& key)
	{
		return _ht.Find(key);
	}

	bool erase(const K& key)
	{
		return _ht.Erase(key);
	}

private:
	HashTable<K, pair<const K, V>, KeyOfT, Hash> _ht;
};

unordered_set.h

#pragma once


template<class K, class Hash = HashFunc<K>>
class unordered_set
{
	struct KeyOfT
	{
		const K& operator()(const K& key)
		{
			return key;
		}
	};

public:
	typedef typename HashTable<K, K, KeyOfT, Hash>::const_iterator iterator;
	typedef typename HashTable<K, K, KeyOfT, Hash>::const_iterator const_iterator;

	const_iterator begin() const
	{
		return _ht.begin();
	}

	const_iterator end() const
	{
		return _ht.end();
	}

	pair<const_iterator, bool> insert(const K& key)
	{
		auto ret = _ht.Insert(key);
		return pair<const_iterator, bool>(const_iterator(ret.first._node, ret.first._pht, ret.first._hashi), ret.second);
	}

	iterator find(const K& key)
	{
		return _ht.Find(key);
	}

private:
	HashTable<K, K, KeyOfT, Hash> _ht;
};

HashTable.h

#pragma once


template<class T>
struct HashNode
{
	HashNode(const T& data)
		:_data(data)
		, _next(nullptr)
	{}
	T _data;
	HashNode<T>* _next;
};


template<class K>
struct HashFunc
{
	size_t operator()(const K& key)
	{
		return (size_t)key;
	}
};
template<>
struct HashFunc<string>
{
	size_t operator()(const string& key)
	{
		size_t sum = 0;
		for (auto& e : key)
		{
			sum *= 31;
			sum += e;
		}
		return sum;
	}
};

//前置声明
template<class K, class T, class KeyOfT, class Hash>
class HashTable;

//迭代器
template<class K, class T, class Ref, class Ptr, class KeyOfT, class Hash = HashFunc<K>>
struct _HTIterator
{
	typedef HashNode<T> Node;
	typedef _HTIterator<K, T, Ref, Ptr, KeyOfT, Hash> Self;
	Node* _node;
	size_t _hashi;
	const HashTable<K, T, KeyOfT, Hash>* _pht;

	_HTIterator(Node* node, HashTable<K, T, KeyOfT, Hash>* pht, size_t hashi)
		:_node(node)
		, _hashi(hashi)
		, _pht(pht)
	{}

	_HTIterator(Node* node, const HashTable<K, T, KeyOfT, Hash>* pht, size_t hashi)
		:_node(node)
		, _hashi(hashi)
		, _pht(pht)
	{}

	Self& operator++()
	{
		if (_node->_next)
		{
			_node = _node->_next;
		}
		else//需要哈希表
		{
			++_hashi;
			while (_hashi < _pht->_tables.size())
			{
				if (_pht->_tables[_hashi])
				{
					_node = _pht->_tables[_hashi];
					break;
				}
				++_hashi;
			}
			if (_hashi == _pht->_tables.size())
			{
				_node = nullptr;
			}
		}
		return *this;
	}

	bool operator!=(const Self& s)
	{
		return _node != s._node;
	}

	Ref operator*()
	{
		return _node->_data;
	}

	Ptr operator->()
	{
		return &(_node->_data);
	}

};




//哈希桶
template<class K, class T, class KeyOfT, class Hash = HashFunc<K>>
class HashTable
{
public:
	typedef HashNode<T> Node;

	//为了访问HashTable的私有成员
	template<class K, class T, class Ref, class Ptr, class KeyOfT, class Hash>
	friend struct _HTIterator;
	typedef _HTIterator<K, T, T&, T*, KeyOfT, Hash> iterator;
	typedef _HTIterator<K, T, const T&, const T*, KeyOfT, Hash> const_iterator;

	Hash hf;
	KeyOfT kot;
	HashTable()
	{
		_tables.resize(10, nullptr);
	}

	~HashTable()
	{
		for (size_t i = 0; i < _tables.size(); i++)
		{
			Node* cur = _tables[i];
			while (cur)
			{
				Node* next = cur->_next;
				delete cur;
				cur = next;
			}
		}
	}

	iterator begin()
	{
		for (size_t i = 0; i < _tables.size(); i++)
		{
			if (_tables[i])
			{
				return iterator(_tables[i], this, i);
			}
		}

		return end();
	}

	iterator end()
	{
		return iterator(nullptr, this, -1);
	}

	const_iterator begin() const
	{
		for (size_t i = 0; i < _tables.size(); i++)
		{
			if (_tables[i])
			{
				return const_iterator(_tables[i], this, i);
			}
		}

		return end();
	}

	const_iterator end() const
	{
		return const_iterator(nullptr, this, -1);
	}

    pair<iterator, bool> Insert(const T& data)
	{
		iterator it = Find(kot(data));
		if (it != end())
			return make_pair(it, false);
	    //扩容
		if (_n / _tables.size() == 1)
		{
			size_t newSize = _tables.size() * 2;
			vector<Node*> newTables;
			newTables.resize(newSize, nullptr);
			for (size_t i = 0; i < _tables.size(); i++)
			{
				Node* cur = _tables[i];
				while (cur)
				{
					size_t hashi = hf(kot(cur->_data)) % newTables.size();
					cur->_next = newTables[hashi];
					newTables[hashi] = cur;
				}
				_tables[i] = nullptr;
			}
			_tables.swap(newTables);
		}

		size_t hashi = hf(kot(data)) % _tables.size();
		Node* newnode = new Node(data);
		newnode->_next = _tables[hashi];
		_tables[hashi] = newnode;
		_n++;

		return make_pair(iterator(newnode, this, hashi), true);
	}

	iterator Find(const K& key)
	{
		size_t hashi = hf(key) % _tables.size();
		Node* cur = _tables[hashi];
		while (cur)
		{
			if (kot(cur->_data) == key)
			{
				return iterator(cur, this, hashi);
			}
			cur = cur->_next;
		}
		return end();
	}

	bool Erase(const K& key)
	{
		size_t hashi = hf(key) % _tables.size();
		Node* cur = _tables[hashi];
		Node* prev = nullptr;
		if (kot(cur->_data) == key)
		{
			_tables[hashi] = nullptr;
			return true;
		}
		while (cur)
		{
			if (kot(cur->_data) == key)
			{
				prev->_next = cur->_next;
				delete cur;
				return true;
			}
			prev = cur;
			cur = cur->_next;
		}
		return false;
	}

private:
	vector<Node*> _tables;
	size_t _n = 0;
};

 3.测试用例

#include<iostream>
#include<vector>
#include<string>
#include<assert.h>
#include<utility>

using namespace std;
#include"HashTable.h"
#include"myunordered_set.h"
#include"myunordered_map.h"

void test()
{
	//HashTable<string, int> ht;
	//ht.Insert(make_pair("西瓜", 1));
	//HashNode<string, int>* ret = ht.Find("西瓜");
	//ret->_kv.second++;
	//cout << ret->_kv.first << ":" << ret->_kv.second << endl;;
	//ht.Insert(make_pair("桃子", 1));
	//ht.Insert(make_pair("桃子", 2));
	//ht.Insert(make_pair("苹果", 1));
}

//void testset()
//{
//	unordered_set<string> us;
//	us.insert("西瓜");
//	us.insert("香蕉");
//	us.insert("苹果");
//	us.insert("西瓜");
//
//	us.erase("西瓜");
//	HashNode<string>* ret = us.find("香蕉");
//	cout << ret->_data << endl;
//}

//void testmap()
//{
//	string arr[] = { "西瓜", "香蕉", "西瓜", "苹果", "西瓜", "西瓜", "香蕉", "西瓜" };
//	unordered_map<string, int> up;
//	for (auto e : arr)
//	{
//		HashNode<pair<string, int>>* ret = up.find(e);
//		if (ret)
//		{
//			ret->_data.second++;
//			cout << ret->_data.first << ":" << ret->_data.second << endl;
//
//		}
//		else
//		{
//			up.insert(make_pair(e, 1));
//		}
//	}
//	
//}

void test_set()
{
	// 17:05
	unordered_set<int> us;
	us.insert(5);
	us.insert(15);
	us.insert(52);
	us.insert(3);

	unordered_set<int>::iterator it = us.begin();
	while (it != us.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

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

void test_map()
{
	//unordered_map<string, string> dict;
	//dict.insert(make_pair("sort", ""));
	//dict.insert(make_pair("string", "ַ"));
	//dict.insert(make_pair("insert", ""));

	//for (auto& kv : dict)
	//{
	//	//kv.first += 'x';
	//	kv.second += 'x';

	//	cout << kv.first << ":" << kv.second << endl;
	//}
	//cout << endl;

	string arr[] = { "西瓜", "苹果", "苹果", "胡萝卜", "梨子", "橘子", "哈密瓜", "桃子", "西瓜", "西瓜", "梨子" };
	unordered_map<string, int> count_map;
	for (auto& e : arr)
	{
		count_map[e]++;
	}

	for (auto& kv : count_map)
	{
		cout << kv.first << ":" << kv.second << endl;
	}
	cout << endl;
}

int main()
{
	//test();
	//testset();
	//testmap();
	//test_set();
	test_map();
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/166035.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++】泛型编程 ⑦ ( 模板类常用用法 | 模板类声明 | 模板类调用 | 模板类作为函数参数 )

文章目录 一、类模板基础用法1、类模板声明定义2、类模板使用3、类模板做函数参数 二、完整代码示例1、代码示例2、执行结果 一、类模板基础用法 1、类模板声明定义 上一篇博客中 , 【C】泛型编程 ⑥ ( 类模板 | 类模板语法 | 代码示例 ) 讲解了模板类的基础语法 , 模板类声明如…

三菱PLC 模拟量输出模拟量转换功能块S_RTI(内嵌ST)

模拟量输出模拟量转换功能块S_RTI算法原理和公式介绍请参考下面文章链接: PLC模拟量输出 模拟量转换FC S_RTI-CSDN博客文章浏览阅读5.3k次,点赞2次,收藏11次。1、本文主要展示西门子博途模拟量输出转换的几种方法, 方法1:先展示下自编FC:计算公式如下:intput intput Rea…

实战项目:VB龟兔赛跑游戏+猜数字游戏

文章目录&#xff1a; 一&#xff1a;效果演示 二&#xff1a;实现思路 三&#xff1a;代码实现 form1 效果图 代码 form2 效果图 代码 form3 效果图 代码 一&#xff1a;效果演示 效果图◕‿◕✌✌✌ 代码下载 二&#xff1a;实现思路 窗口1&#xff1a;龟兔赛…

数据结构【DS】特殊二叉树

完全二叉树 叶子结点只能出现在最下层和次下层, 最下层的叶子结点集中在树的左部完全二叉树中, 度为1的节点数 0个或者1个【计算时可以用这个快速计算, 配合&#x1d45b;0&#x1d45b;21】若n为奇数&#xff0c;则分支节点每个都有左右孩子&#xff1b;若n为偶数&#xff0…

Python---return返回值

return返回值 返回值&#xff1a;很多函数在执行完毕后&#xff0c;会通过return关键字返回一个结果给 调用它的位置。 return 英 /rɪˈtɜːn/ n. 回来&#xff0c;返回&#xff1b; 思考&#xff1a;如果一个函数需要两个return (如下所示)&#xff0c;程序如何执行&…

C语言——1.入门须知

文章目录 1.C语言的简要概述1.1.C语言类比自然语言1.2.计算机语言的发展1.3.C语言在当今的地位1.4.C语言的优势和劣势1.4.1.C语言的优势1.4.2.C语言的劣势 2.C语言的应用场景3.C语言的学习路径3.1.学习目的3.2.学习路径3.3.学习资源3.3.1.推荐书籍3.3.2.推荐课程3.3.3.推荐题库…

Nodejs--Express框架使用

目录 一.概念 二.项目目录结构 三.app.js 四.项目需要的中间件 五.Mysql连接 六.日志配置 七.实体模型配置 八.统一结果封装 九.app.js的详细配置 十.自定义登录拦截器 十一.route路由配置 十二.controller处理 十二&#xff1a;静态页面&#xff1a; 十三&#xff…

男子遗失30万天价VERTU唐卡手机,警察2小时“光速”寻回

今天&#xff0c;一则“男子丢失30万元手机女子捡到一位老年机”的新闻迅速冲上热搜第一&#xff0c;引发全网热议。据宿城公安消息&#xff1a;近日&#xff0c;江苏省宿迁市市民王先生在购物时不慎失落了一部价值30万元的全球知名奢侈品VERTU手机&#xff0c;被民警2个多小时…

基于springboot实现家政服务管理平台项目【项目源码+论文说明】计算机毕业设计

摘要 随着家政服务行业的不断发展&#xff0c;家政服务在现实生活中的使用和普及&#xff0c;家政服务行业成为近年内出现的一个新行业&#xff0c;并且能够成为大众广为认可和接受的行为和选择。设计家政服务管理平台的目的就是借助计算机让复杂的销售操作变简单&#xff0c;…

链表的增删改查(python实现)

链表的增删改查 使用python实现链表的增删改查 增 add(val)&#xff1a;在头结点处增加&#xff0c;左插入append(val)&#xff1a;在尾结点处增加&#xff0c;右插入 删 remove_single(target)&#xff1a;删除值为target的第一个节点remove_all(target)&#xff1a;删除值为…

Linux僵尸进程

Linux僵尸进程 一、僵尸进程简介二、僵尸进程的危害三、避免僵尸进程的方法 一、僵尸进程简介 如果父进程比子进程先退出&#xff0c;子进程将被1号进程托管&#xff08;这也是一种让程序在后台运行的方法&#xff09;。如果子进程比父进程先退出&#xff0c;而父进程没有处理…

基于SSM的“鲜花”电子商务平台设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

通过汇编理解cortex-m3:第0章

第0章&#xff1a;准备工作 基本想法&#xff1a;利用汇编和gdb调试&#xff0c;来学习cortex-m3汇编指令&#xff0c;以及一些寄存器的功能。 软件和硬件&#xff1a; 硬件&#xff1a;韦东山瑞士军刀中的最小核心板&#xff08;STM32F103C8T6&#xff09; STLINK-V2&#…

基于java web个人财务管理系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

PyCharm:PyCharm新建.py文件时自动带出指定内容

在pycharm中加上指定内容&#xff0c;每次新建.py文件都会自动带出指定内容 操作&#xff1a; File—Setting—Editor----File and Code Templates--Python Script 在右侧窗口中加上如下信息 # encoding: utf-8 # author: Jeffrey # file: ${NAME}.py # time: ${DATE} ${TI…

【Java SE】循环一些基本练习

判定一个数字是否是素数 public class Test {public static int is_sushu(int n) {if(n 1) {return 0;}int i ;for (i 2; i < Math.sqrt(n); i) {if(n % i 0 ) {break;}}if (i > n) {return 1;}return 0;}public static void main(String[] args) {Scanner scanner …

kafka 磁盘扩容与数据均衡实在操作讲解

文章目录 一、概述1&#xff09;Kafka 磁盘扩容概述2&#xff09;Kafka 数据均衡概述 二、K8s 集群部署三、kafka on k8s 环境部署1&#xff09;安装 helm2&#xff09;安装 zookeeper1、添加源并下载部署包2、修改配置3、开始安装 zookeeper4、测试验证5、卸载 3&#xff09;安…

uview-plus中二级菜单左右联动更改为uni-app+vue3+vite写法

uview-plus3.0重磅发布&#xff0c;全面的Vue3移动组件库 该插件使用的vue2写法&#xff0c;但支持vue3引用&#xff0c;在此基础上修改为uni-appvue3vite; <template><view class"u-wrap mainClass"><!-- <back-header :title"pageTitle&quo…

【Linux】-进程间通信-命名管道文件(没有关系的进程间进行通信),以及写一个日志模板

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

mysql数据库【进阶篇】

1.存储引擎 1.1 mysql的体系结构 连接层&#xff1a;最上层是一些客户端和链接服务&#xff0c;主要完成- -些类似于连接处理、授权认证、及相关的安全方案。服务器也会为安全接入的每个客户端验证它所具有的操作权限。服务层&#xff1a;第二层架构主要完成大多数的核心服务功…