C++中Map的使用及介绍+operator[ ]的底层实现(超详细版本+代码+底层剖析)

基础介绍

帮助文档

链接: Map帮助文档

特性

map的特性是:所有元素都会根据键值自动的排序。map的所有元素都是pair,同时拥有实值(value)和键值(key)。pair的第一个元素被视为键值,第二个元素被视为实值。map不允许两个元素同时拥有同一个键值,也就是说map的键值是唯一的。(来源:STL源码剖析)

我们可以通过map 的送代器政变map 的元素肉容吗?
如果想要修正元素的健值,答突是不行,因为map 元業的健值关 系到 map 元茶的排列规则。任意改变map元素键值将会严重破坏mEp 组织。但如果想要修正元素的实值,答案是可以,因为map 元素的实值并不影响 map 元素的排列规则。因此,map iterators 既不是一种constant iterators, 也不是一种mutable iterators。
map 拥有和 Tist 相同的某些性质:
当容户端对它进行元素新增操作(insert)或删除操作 (erase)时,操作之前的所有迭代器,在操作完成之后都依然有效。当然,被州除的那个元素的迭代器必然是个例外。由于RB-tree 是一种平衡二叉搜索树,自动排序的效果很不错,所以标准的 STLImap 即以! RB-tree 为底层机制。又由于 map 所开放的各种操作接口,RB-tree 也都提供了,所以几乎所有的map 操作行为,都只是转调用 RB-tree 的操作行为而已。

主要函数介绍

Pair构造函数

图1 pair构造函数

迭代器

图2 map迭代器介绍主要介绍遍历和输出打印
图3 迭代器示例

Insert函数

插入:用统计字母出现次数为例子

图4 插入

我们看看插入函数的介绍:
图5 插入函数帮助文档**pair<iterator,bool> insert (const value_type& val);**这里的插入有两个返回值,其中第一个返回值是一个迭代器,也就是键值,如果map容器中没有相同的值,就插入成功并返回插入后的迭代器,如果存在就返回当前键值的迭代器。第二个返回值是一个bool值,如果map中已经存在相同的值就返回false,反之就返回true。

自己改造实现:

图6 实现插入
图7 运行结果
和上面一样,说了这么多,就是为了理解Insert的底层,返回的是一个迭代器+一个bool值,这些方法都不常用,了解即可 。接下来到我们的重头戏:Operator[ ];

Operator [ ]

帮助文档

图8 Operator帮助文档

由图可知:1.返回的是对键值等效于 k 的元素的映射值的引用。 2.底层是调用Insert接口。
上述例子用Operator[ ]实现:
图9
一句代码统计了次数。这就是返回引用的好处:1.查找对应的key 2.修改对应的key。
再回到头看刚开始的dict用operater[ ]实现:
图10 dict实现

测试代码

using namespace std;
#include<iostream>
#include <map>
void Test1()
{
	map<string, string> dict;
	//pair构造函数
	dict.insert(pair<string, string>("abandon", "放弃"));//插入1
	pair<string, string>kv("insert", "插入");
	dict.insert(kv);//插入2

	//mark_pair
	dict.insert(make_pair("erase", "清空"));// 插入3 调用mark_pair 来构造pair




	dict["operator"] = "重载";//插入+修改(实值改为重载)
	dict["abandon"] = "放弃、抛弃";//查找+修改
	dict["left"];//插入

	遍历
	//auto it = dict.begin();
	//cout << "方式1 输出打印:" << endl;
	//while (it!=dict.end())
	//{
	//  //pair不支持IO流 所以要用特殊的方式处理 
	//	//方式1
	//	cout << (*it).first + ":" << (*it).second << endl;
	//	it++;
	//}
	//方式2 范围for
	cout << "方式2 输出打印:" << endl;
	for (const auto& kv : dict)
	{
		cout << kv.first << ":" << kv.second << endl;
	}
}
void Test2() 
{
	//统计每个字母出现的次数
	string arr[] = { "A","A","B","C","A","P","D","H","H","C" };
	map<string, int>countmap;
	//for (auto&str:arr)
	//{
	//	//先用find找一下是否存在 不存在就插入 存在count++
	//	map<string, int>::iterator it = coutmap.find(str);
	//	if (it != coutmap.end())//存在
	//	{
	//		it->second++;
	//	}
	//	else //不存在 插入
	//	{
	//		coutmap.insert(make_pair(str, 1)); 
	//	}
	//}

	//for (auto& str : arr)
	//{
	//	//pair<map<string,int>::iterator,bool> ret 这是函数返回的类型 
	//	//pair<map<string, int>::iterator, bool> ret = countmap.insert(make_pair(str, 1));
	//	//ret的first是迭代器 second是bool类型
	//	auto ret= countmap.insert(make_pair(str, 1));//简化
	//	if (ret.second==false) //存在
	//	{
	//		ret.first->second++; //迭代器指向的键值的second 也就是count++
	//	}

	//}

	for (auto& str :arr)
	{
		countmap[str]++; 
	}


	//打印
	for (const auto& kv : countmap)
	{
		cout << kv.first << ":" << kv.second << endl;
	}
}
int main()
{

	Test1();
	return 0;

}

以上是关于Map知识点的总结,如有不足,欢迎补充,创作不易,多多支持,转载请注明出处,大家一起进步!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C++实现赫夫曼编码及解码的完整代码,其包括了赫夫曼树的构建、编码、解码等操作。 ```cpp #include <iostream> #include <queue> #include <unordered_map> #include <bitset> using namespace std; // 声明结构体 struct TreeNode { char c; int freq; TreeNode* left; TreeNode* right; TreeNode(char _c, int _freq) : c(_c), freq(_freq), left(nullptr), right(nullptr) {} }; // 定义比较函数 struct Compare { bool operator() (TreeNode* a, TreeNode* b) { return a->freq > b->freq; } }; // 构建赫夫曼树 TreeNode* buildHuffmanTree(const unordered_map<char, int>& freqMap) { priority_queue<TreeNode*, vector<TreeNode*>, Compare> pq; for (const auto& p : freqMap) { pq.push(new TreeNode(p.first, p.second)); } while (pq.size() > 1) { TreeNode* left = pq.top(); pq.pop(); TreeNode* right = pq.top(); pq.pop(); int freqSum = left->freq + right->freq; TreeNode* parent = new TreeNode('#', freqSum); parent->left = left; parent->right = right; pq.push(parent); } return pq.top(); } // 递归构建编码表 void buildCodeTable(TreeNode* root, unordered_map<char, string>& codeTable, string path = "") { if (root == nullptr) return; if (root->left == nullptr && root->right == nullptr) { codeTable[root->c] = path; return; } buildCodeTable(root->left, codeTable, path + "0"); buildCodeTable(root->right, codeTable, path + "1"); } // 对文本进行编码 string encode(const string& text, const unordered_map<char, string>& codeTable) { string encodedText = ""; for (char c : text) { encodedText += codeTable.at(c); } return encodedText; } // 对编码后的文本进行解码 string decode(const string& encodedText, TreeNode* root) { string decodedText = ""; TreeNode* node = root; for (char bit : encodedText) { if (bit == '0') { node = node->left; } else { node = node->right; } if (node->left == nullptr && node->right == nullptr) { decodedText += node->c; node = root; } } return decodedText; } // 打印编码表 void printCodeTable(const unordered_map<char, string>& codeTable) { for (const auto& p : codeTable) { cout << p.first << " : " << p.second << endl; } } int main() { // 定义测试数据 string text = "abccdeefffgghhi"; unordered_map<char, int> freqMap; for (char c : text) { freqMap[c]++; } // 构建赫夫曼树 TreeNode* root = buildHuffmanTree(freqMap); // 构建编码表 unordered_map<char, string> codeTable; buildCodeTable(root, codeTable); // 打印编码表 printCodeTable(codeTable); // 对文本进行编码 string encodedText = encode(text, codeTable); cout << "Encoded text : " << encodedText << endl; // 对编码后的文本进行解码 string decodedText = decode(encodedText, root); cout << "Decoded text : " << decodedText << endl; return 0; } ``` 下面是针对测试数据 abccdeefffgghhi 的运行结果及分析: 编码表: a : 111 b : 110 c : 10 d : 0000 e : 01 f : 001 g : 0001 h : 100 i : 101 编码后的文本:1101111011010100001110010000000010001010110101 解码后的文本:abccdeefffgghhi 可以看到,赫夫曼编码可以有效地压缩文本,并且对于出现频率较高的字符,它们的编码比较短,因此压缩效果更好。同时,赫夫曼编码也具有一定的容错性,即使编码出现错误的位,也不会影响整个文本的解码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值