c++数据结构10——map结构详解

一、引言:为什么需要map?

考虑这样一个问题:在一段文本中统计每个单词出现的次数,并找出出现次数最多的单词。例如输入:

red apple ,red apple,i love red

期望输出:red 3

传统数组无法解决这个问题,因为:

  1. 数组索引只能是整数,不能是字符串

  2. 文本中的单词数量不确定

  3. 需要动态存储键值对

map容器正是为解决这类问题而设计的关联容器,它提供了高效的键值对存储和检索能力。

二、map基本概念

1.核心特点

  • 键值对存储:每个元素包含一个键(key)和一个值(value)

  • 自动排序:元素根据key自动升序排列

  • 唯一键:每个key在map中唯一

  • 高效操作:查找、插入、删除时间复杂度为O(log n)

2.底层实现

map基于红黑树(自平衡二叉查找树)实现,这使得它能够:

  1. 保持元素有序

  2. 提供高效的查找操作

  3. 动态调整树结构保持平衡

三、map的定义与基本操作

1.头文件与定义

#include <map>  // 必须包含的头文件

// 定义map的基本语法
map<key类型, value类型> 映射名称;

// 示例:字符串到整数的映射
map<string, int> wordCount;

2.三种插入元素方式

  1. 下标操作符[]

wordCount["apple"] = 3;  // 插入键"apple",值3

     2.insert()函数

wordCount.insert(make_pair("banana", 5));  // 使用make_pair创建键值对

     3.value_type

   wordCount.insert(map<string, int>::value_type("orange", 2));
   注意:使用insert插入已存在的键不会覆盖原值,而使用[]会覆盖原值
 

3.访问与遍历map元素

    1. 下标访问

 cout << wordCount["apple"];  // 输出3
 注意 :使用不存在的键访问会自动创建该键,值为0

    2. 迭代器遍历

for(map<string, int>::iterator it = wordCount.begin(); it != wordCount.end(); it++) {
    cout << it->first << ": " << it->second << endl;  // first是键,second是值
}

    3. C++11范围for循环

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

四、常用成员函数

函数功能示例时间复杂度
find(key)查找指定键auto it = m.find("apple");O(log n)
count(key)统计键出现次数if(m.count("apple") > 0) {...}O(log n)
size()返回元素数量int num = m.size();O(1)
empty()判断是否为空if(m.empty()) {...}O(1)
erase(key)删除指定键m.erase("apple");O(log n)
clear()清空mapm.clear();O(n)

五、应用实例:统计单词频率

问题描述

输入一段文本,统计每个单词的出现频率,输出出现次数最多的单词及其次数

输入样例

Can a can can a can? It can!

输出结果

can 5

解题思路

  1. 分割文本为单词

  2. 统一转换为小写

  3. 使用map统计每个单词出现次数

  4. 遍历map找到最大频率的单词

完整代码

#include <iostream>
#include <map>
#include <cctype> // 用于tolower()
using namespace std;

// 处理单词:转换为小写并移除非字母字符
string processWord(string word) {
    string result = "";
    for(char c : word) {
        if(isalpha(c)) { // 只保留字母
            result += tolower(c); // 转换为小写
        }
    }
    return result;
}

int main() {
    map<string, int> wordCount;
    string word;
    
    while(cin >> word) { // 逐个读取单词
        string processed = processWord(word);
        if(!processed.empty()) { // 忽略空单词
            wordCount[processed]++; // 计数增加
        }
    }
    
    // 找出出现次数最多的单词
    string mostFrequent;
    int maxCount = 0;
    
    for(auto& pair : wordCount) {
        if(pair.second > maxCount || 
           (pair.second == maxCount && pair.first < mostFrequent)) {
            mostFrequent = pair.first;
            maxCount = pair.second;
        }
    }
    
    cout << mostFrequent << " " << maxCount << endl;
    return 0;
}

六、map的性能特点与最佳实践

性能特点

  1. 优点

    • 自动排序

    • 键唯一性保证

    • 高效的查找操作(O(log n))

  2. 缺点

    • 内存占用较大(每个节点需要额外指针)

    • 插入/删除可能引起树结构调整

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值