【二十六】【C++】Map和Set

K模型与KV模型

在数据结构中,二叉搜索树(BST)的应用通常围绕着两种基本模型:键模型(K模型)和键值对模型(KV模型)。这两种模型定义了树中节点存储数据的方式,以及如何通过这些数据进行查找、插入和删除操作。

K模型(键模型)

在K模型中,每个节点存储一个单一的数据项,称为“键”(Key)。这个模型的核心特性是:

唯一性:树中每个键都是唯一的,不允许重复。

有序性:树中任意节点的左子树只包含键小于该节点的键的节点,其右子树只包含键大于该节点的键的节点。

操作:基本操作包括插入新键、查找键和删除键。所有操作都依赖于键之间的比较。

K模型的二叉搜索树适用于需要快速查找、插入和删除单一数据项的场景,如集合数据类型的实现。

KV模型(键值对模型)

KV模型扩展了K模型,使得每个节点存储两个数据项:一个是“键”(Key),另一个是与键相关联的“值”(Value)。这个模型的特性包括:

键的唯一性和有序性:与K模型相同,键在树中是唯一的,并且树的结构保证了键的有序性。

值的关联性:每个键都关联一个特定的值。值可以是任何类型的数据,如数字、字符串或更复杂的对象。

操作:除了基本的插入、查找和删除操作外,KV模型还支持根据键更新关联值的操作。

KV模型的二叉搜索树广泛应用于实现映射(Map)或字典(Dictionary)数据结构,其中需要根据唯一键快速查找、更新或删除关联的值。

改造二叉搜索树为KV结构

 
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

template<class K, class V>
struct BSTNode {
    BSTNode(const K&key = K(), const V& value = V())
        : _pLeft(nullptr)
        , _pRight(nullptr)
        , _key(key)
        , _value(value) {

    }
    BSTNode<K, V>* _pLeft;
    BSTNode<K, V>* _pRight;
    K _key;
    V _value;
 };

template<class K, class V>
class BSTree {
        typedef BSTNode<K, V> Node;
        typedef Node* PNode;
    public:
        BSTree(): _pRoot(nullptr) {}
        PNode Find(const K& key) {
            Node* cur = _pRoot;
            while (cur) {
                if (key == cur->_key)
                    return cur;
                else if (key < cur->_key)
                    cur = cur->_pLeft;
                else
                    cur = cur->_pRight;
            }

            return nullptr;
        };
        bool Insert(const K& key, const V&value) {
            // 1. 空树---
            // 新插入的节点应该是跟节点
            if (nullptr == _pRoot) {
                _pRoot = new Node(key, value);
                return true;
            }

            // 2. 树非空
            // a. 找待插入节点在树中的位置--->按照二叉搜索树的性质
            Node* cur = _pRoot;
            Node* parent = nullptr;
            while (cur) {
                parent = cur;
                if (key < cur->_key)
                    cur = cur->_pLeft;
                else if (key > cur->_key)
                    cur = cur->_pRight;
                else
                    return false;
            }

            // 树中不存在值为data的节点
            // b. 插入新节点
            cur = new Node(key, value);
            if (key < parent->_key)
                parent->_pLeft = cur;
            else
                parent->_pRight = cur;

            return true;
        };
        bool Erase(const K& key) {
            return false;
        };
        void InOrder() {
            _InOrder(_pRoot);
            cout << endl;
        }

    private:
        void _InOrder(Node* proot) {
            if (proot) {
                _InOrder(proot->_pLeft);
                cout << proot->_key << " 个数:" << proot->_value << endl;
                _InOrder(proot->_pRight);
            }
        }
        PNode _pRoot;
 };

void TestBSTree3() {
    BSTree<string, string> dict;
    dict.Insert("string", "字符串");
    dict.Insert("tree", "树");
    dict.Insert("left", "左边、剩余");
    dict.Insert("right", "右边");
    dict.Insert("sort", "排序");
    string str;
    while (cin >> str) {
        if(str[0] == EOF){return;}
        BSTNode<string, string>* ret = dict.Find(str);
        if (ret == nullptr) {
            cout << "单词拼写错误,词库中没有这个单词:" << str << endl;
        } else {
            cout << str << "中文翻译:" << ret->_value << endl;
        }
    }


 }

void TestBSTree4() {
    // 统计水果出现的次数
    string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
                     "苹果", "香蕉", "苹果", "香蕉"
                   };
    BSTree<string, int> countTree;
    for (const auto& str : arr) {
// 先查找水果在不在搜索树中
 // 1、不在,说明水果第一次出现,则插入<水果, 1>
 // 2、在,则查找到的节点中水果对应的次数++
 //BSTreeNode<string, int>* ret = countTree.Find(str);
        auto ret = countTree.Find(str);
        if (ret == NULL) {
            countTree.Insert(str, 1);
        } else {
            ret->_value++;
        }
    }
    countTree.InOrder();
 }

int main() {
    TestBSTree3();
    TestBSTree4();
    return 0;
 }

Map、MultMap的探究

Map是一种关联容器,它存储由键值和映射值组成的元素,遵循特定的顺序。

Map中,键值通常用于对元素进行排序和唯一标识,而映射值存储与该键相关联的内容。键和映射值的类型可能不同,并且被组合在一起作为成员类型value_type,它是一个pair类型,结合了键和映射值:

typedef pair<const Key, T> value_type;

Map中,元素总是按其键值进行排序,遵循特定的严格弱排序准则,由其内部比较对象(Compare类型)指示。

相比unordered_map容器,Map容器通常访问单个元素时速度较慢,但它们允许根据其顺序直接迭代子集。

Map中,可以使用方括号运算符(operator[])直接通过其相应的键访问映射值。

Map通常以二叉搜索树的形式实现。

 
#include <iostream>
using namespace std;

#include <map>
#include <string>


void TestMap1()
 {
    map<string, string> m1;
    map<string, string> m2{ {"apple","苹果"}, {"orange", "橙子"}, {"banana", "香蕉"} };
    auto m3 = m2;   // 调用拷贝构造
    
     map<string, string> m4(m2.begin(), m2.end());
 }


void TestMap2()
 {
    map<string, string> m;
    
     // 通过insert直接往map中插入键值对
    pair<string, string> p("orange", "橙子");
    m.insert(p);
    m.insert(pair<string, string>("banana", "香蕉"));
    m.insert(make_pair("apple", "苹果"));
    
     cout << m.size() << endl;
    
     // m[key]--->表明:返回key对应的value
    cout << m["orange"] << endl;
    
     // m[key] = newvalue;  使用newvalue给map中key对应的value进行赋值
    m["orange"] = "橘子";
    
     // 如果通过m[key]访问key对应的value时,如果key不存子?
    // m会使用当前key与一个默认的value构成一个键值对<key, 默认value>插入到m中
    // 然后将key对应的默认的value返回来
    cout<<m["peach"]<<endl;
    
     m["pair"] = "梨";
    
     // map中已经存在orange,在插入一个orange看能否成功
    m.insert(make_pair("orange", "橙子"));
    cout << m.size() << endl;
    
     
     // 对map中的元素进行遍历
    //std::map<std::string, std::string>::iterator it = m.begin();
    auto it = m.begin();
    while (it != m.end())
    {
        cout << "<" << it->first << "," << it->second << ">" << endl;
        ++it;
    }
    cout << endl;
    
     // e 就是m中所存在的键值对的别名
    for (auto& e : m)
    {
        cout << "<" << e.first << "," << e.second << ">" << endl;
    }
    cout << endl;
    
     m.erase("apple");
    
     it = m.find("orange");
    if (it != m.end())
    {
        m.erase(it);
    }
    
     for (auto& e : m)
    {
        cout << "<" << e.first << "," << e.second << ">" << endl;
    }
    cout << endl;
 }

void TestMultiMap()
 {
    multimap<string, string> m;
    m.insert(make_pair("apple", "苹果"));
    m.insert(make_pair("apple", "苹果"));
    m.insert(make_pair("apple", "苹果"));
    m.insert(make_pair("apple", "苹果"));
    
     m.erase("apple");
 }


int main(){
    TestMap1();
    TestMap2();
    TestMultiMap();
    
}

Map的创建

 
 
void TestMap1()
 {
    map<string, string> m1;
    map<string, string> m2{ {"apple","苹果"}, {"orange", "橙子"}, {"banana", "香蕉"} };
    auto m3 = m2;   // 调用拷贝构造
    
     map<string, string> m4(m2.begin(), m2.end());
 }

map<string, string> m1;:创建了一个空的map容器m1

map<string, string> m2{ {"apple","苹果"}, {"orange", "橙子"}, {"banana", "香蕉"} };:创建了一个带有初始值的map容器m2,其中包含三个键值对,键为字符串类型,值为字符串类型。

auto m3 = m2;:创建了一个新的map容器m3,并将m2拷贝到m3中。这里使用了auto进行类型推导,实际上调用了拷贝构造函数。

map<string, string> m4(m2.begin(), m2.end());:创建了一个新的map容器m4,并通过迭代器范围初始化,从m2的开始迭代器到结束迭代器,复制了m2的所有元素。

Map的基本使用

 
 
void TestMap2()
 {
    map<string, string> m;
    
     // 通过insert直接往map中插入键值对
    pair<string, string> p("orange", "橙子");
    m.insert(p);
    m.insert(pair<string, string>("banana", "香蕉"));
    m.insert(make_pair("apple", "苹果"));
    
     cout << m.size() << endl;
    
     // m[key]--->表明:返回key对应的value
    cout << m["orange"] << endl;
    
     // m[key] = newvalue;  使用newvalue给map中key对应的value进行赋值
    m["orange"] = "橘子";
    
     // 如果通过m[key]访问key对应的value时,如果key不存子?
    // m会使用当前key与一个默认的value构成一个键值对<key, 默认value>插入到m中
    // 然后将key对应的默认的value返回来
    cout<<m["peach"]<<endl;
    
     m["pair"] = "梨";
    
     // map中已经存在orange,在插入一个orange看能否成功
    m.insert(make_pair("orange", "橙子"));
    cout << m.size() << endl;
    
     
     // 对map中的元素进行遍历
    //std::map<std::string, std::string>::iterator it = m.begin();
    auto it = m.begin();
    while (it != m.end())
    {
        cout << "<" << it->first << "," << it->second << ">" << endl;
        ++it;
    }
    cout << endl;
    
     // e 就是m中所存在的键值对的别名
    for (auto& e : m)
    {
        cout << "<" << e.first << "," << e.second << ">" << endl;
    }
    cout << endl;
    
     m.erase("apple");
    
     it = m.find("orange");
    if (it != m.end())
    {
        m.erase(it);
    }
    
     for (auto& e : m)
    {
        cout << "<" << e.first << "," << e.second << ">" << endl;
    }
    cout << endl;
 }

MultiMap

 
 
void TestMultiMap()
 {
    multimap<string, string> m;
    m.insert(make_pair("apple", "苹果"));
    m.insert(make_pair("apple", "苹果"));
    m.insert(make_pair("apple", "苹果"));
    m.insert(make_pair("apple", "苹果"));
    
     m.erase("apple");
 }

创建了一个空的multimap容器 m

使用 insert 函数向multimap容器中插入多个键值对,这些键值对的键都是 "apple",值都是 "苹果"。

使用 erase 函数删除multimap容器中键为 "apple" 的所有键值对。由于multimap容器允许存储相同的键,因此会删除所有键为 "apple" 的键值对,而不仅仅是第一个或最后一个。

Set、MulitSet的探究

集合(Sets)是一种容器,它存储具有唯一性的元素并遵循特定的顺序。

在一个集合中,元素的值也是唯一标识它的(值本身即是键,类型为 T),每个值必须是唯一的。集合中元素的值一旦在容器中,就不能被修改(元素始终是 const),但它们可以被插入或从容器中移除。

在内部,集合中的元素总是按照特定的严格弱排序准则进行排序,这个准则由其内部比较对象(Compare 类型)指示。

相比 unordered_set 容器,集合容器通常访问单个元素时速度较慢,但它们允许根据其顺序直接迭代子集。

集合通常被实现为二叉搜索树。

 
#include <set>
#include <iostream>
using namespace std;

#include <string>
// set使用的场景:去重+排序
void TestSet()
 {
    int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    set<int> s(array, array+sizeof(array)/sizeof(array[0]));
    
     for (auto e : s)
    {
        cout << e << " ";
    }
    cout << endl;
 }

// multiset作用:排序
void TestMultiSet()
 {
    int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    multiset<int> s(array, array + sizeof(array) / sizeof(array[0]));
    
     for (auto e : s)
    {
        cout << e << " ";
    }
    cout << endl;
 }

int main(){
    TestSet();
    TestMultiSet();
 }
 
 
void TestSet()
 {
    int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    set<int> s(array, array+sizeof(array)/sizeof(array[0]));
    
     for (auto e : s)
    {
        cout << e << " ";
    }
    cout << endl;
 }

定义了一个整型数组 array,其中包含了一些整数。

使用数组范围初始化了set容器 s。在初始化时,重复的元素会被自动去重,因此set中不会有重复的元素。

使用范围-based for 循环遍历set容器中的所有元素,并输出它们。由于set容器中的元素是按照一定顺序排列的,因此输出结果也是有序的。

 
 
// multiset作用:排序
void TestMultiSet()
 {
    int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    multiset<int> s(array, array + sizeof(array) / sizeof(array[0]));
    
     for (auto e : s)
    {
        cout << e << " ";
    }
    cout << endl;
 }

定义了一个整型数组 array,其中包含了一些整数。

使用数组范围初始化了multiset容器 s。在初始化时,重复的元素会被保留,因此multiset中可以包含重复的元素,并且会按照一定顺序排列。

使用范围-based for 循环遍历multiset容器中的所有元素,并输出它们。由于multiset容器中的元素是按照一定顺序排列的,因此输出结果也是有序的。

Map的水果数量问题探究

统计输入的水果中每种水果出现的次数,并输出出现次数最多的前 k 种水果。

 
#include <vector>
#include<map>

#include<iostream>
using namespace std;

void GetFavoriteFruit(const vector<string>& fruits,size_t k)
 {
    map<string, size_t> m;
    for (auto e : fruits)
        m[e]++;
    
     multimap<size_t, string, greater<int>> mm;
    for (auto& e : m)
    {
        mm.insert(make_pair(e.second, e.first));
    }
    
     for (auto& e : mm)
    {
        if (k == 0)
            return;
        
         cout << e.second << " ";
        k--;
    }
    cout << endl;
 }



int main()
 {
    
     vector<string> fruits{"1111", "2222", "3333", "2222", "4444", "3333", "5555", "9999", "0000", "3333", "1111", "5555", "2222"};
    GetFavoriteFruit(fruits, 3);
    return 0;
 }

定义一个map来存储每个水果和它出现的次数:

map<string, size_t> m;:这个map以水果名称为键(string类型),以水果出现次数为值(size_t类型)。

遍历fruits向量,统计每种水果的出现次数:

for (auto e : fruits) m[e]++;:对于fruits向量中的每个元素e,在map m中增加它的计数。

定义一个multimap来按出现次数对水果进行排序:

multimap<size_t, string, greater<int>> mm;:这个multimap以水果出现的次数为键(size_t类型),以水果名称为值(string类型)。greater<int>使得元素按键(出现次数)的降序排序。

map m中的元素插入到multimap mm中:

for (auto& e : m) { mm.insert(make_pair(e.second, e.first)); }:遍历map m,将每个元素(即每种水果及其出现次数)插入到multimap mm中,键值对颠倒,使得次数成为键,水果名称成为值。

打印出现次数最多的前k个水果:

for (auto& e : mm) { if (k == 0) return; cout << e.second << " "; k--; }:遍历multimap mm,打印出键值对中的值(即水果名称)。每打印一个减少k的值,直到k为0或遍历完成。由于mm是按次数降序排列的,这保证了最先打印的是出现次数最多的水果。

结尾

最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。

同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。

谢谢您的支持,期待与您在下一篇文章中再次相遇!

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

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

相关文章

区块链游戏解说:什么是 Planet IX

作者&#xff1a;lesleyfootprint.network 编译&#xff1a;cicifootprint.network 数据源&#xff1a;Planet IX Dashboard 什么是 Planet IX Planet IX&#xff0c;一个由原生 IX TOKEN 推动的 Web3 玩赚平台。作为一款 GameFi 策略游戏&#xff0c; Planet IX 上的每项资…

如何修改docker容器的端口映射

要修改 Docker 容器的端口映射&#xff0c;你需要停止并删除现有的容器&#xff0c;然后使用新的端口映射重新运行容器。以下是详细步骤&#xff1a; 停止容器&#xff1a; 使用 docker stop 命令停止正在运行的容器。替换 <container_id> 为你要停止的容器的 ID 或者容器…

浅谈消防设备电源监控系统在高层建筑中的应用

摘要&#xff1a;火灾发生后&#xff0c;非消防电源被切断&#xff0c;火灾报警系统应立即接通消防电源&#xff0c;满足消防设施 处于良好运行状态&#xff0c;对消防设备电源状态的监控是十分必要的。介绍消防设备电源的重要性 和三种类型&#xff0c;分析消防设备电源监控系…

Python中HTTP重定向和重定向链的处理:网络迷宫的导航专家

在网络世界里&#xff0c;有时候&#xff0c;我们访问的URL并不是直接指向我们想要的内容&#xff0c;而是像是一个神秘的迷宫&#xff0c;指引我们绕来绕去。这时候&#xff0c;HTTP重定向就像是迷宫里的路标&#xff0c;告诉我们“嘿&#xff0c;你要找的东西不在这里&#x…

这才是No.1的门禁管理技巧!赶紧抄作业

随着社会的不断发展和科技的飞速进步&#xff0c;安全管理成为各个领域不可或缺的重要环节。在这个背景下&#xff0c;门禁监控系统作为一种先进而高效的安全管理工具逐渐受到了广泛关注和应用。 客户案例 企业大厦管理 在江苏某繁忙的商业大厦中&#xff0c;管理人员常常面临…

【咕咕送书 | 第七期】世界顶级名校计算机专业,都在用哪些书当教材?

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《linux深造日志》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! ⛳️ 写在前面参与规则 ✅参与方式&#xff1a;关注博主、点赞、收藏、评论&#xff0c;任意评论&#xff08;每人最多评论…

七、计算机视觉-图像的ROI区域

文章目录 1、什么是ROI2、ROI如何实现的3、一个案例总结 1、什么是ROI 在计算机视觉中&#xff0c;ROI代表感兴趣区域&#xff08;Region of Interest&#xff09;&#xff0c;它是指图像或视频中被指定为需要特别关注或处理的区域。ROI可以帮助减少计算量&#xff0c;并且在处…

基于JAVA springboot+mybatis 电商书城平台系统设计和实现

基于JAVA springbootmybatis 电商书城平台系统设计和实现 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言 文末获…

初识VUE3

1.VUE3官网 https://cn.vuejs.org/ 2.通过Vite创建项目 全局安装vite npm config set registryhttps://registry.npmmirror.com 使用国内源npm install -g vitelatest 安装vite前要先查看镜像源地址并使用国内镜像源地址 //查看镜像源地址 npm config get registry //更…

Debug|百度OCR识别错误error_code: 216205

1. 什么错误 在使用百度OCR识别时遇到了错误error_code: 216205。 参照文档【百度OCR文字识别 - API文档 - 错误码】中的描述&#xff0c;是我的图片转base64后大于10M 测试两张图片&#xff1a;923k图片的Base64 大于 10M&#xff1b;2M图片的Base64 小于 10M。 # 电脑上看…

Maven的下载安装配置教程

一、简单了解一下什么是Maven Maven就是一款帮助程序员构建项目的工具&#xff0c;我们只需要告诉Maven需要哪些Jar 包&#xff0c;它会帮助我们下载所有的Jar&#xff0c;极大提升开发效率。 1.Maven翻译为“专家“&#xff0c; ”内行”的意思&#xff0c;是著名Apache公司下…

Day16_集合与泛型(泛型类与泛型接口,泛型方法,类型变量的上限与泛型的擦除,类型通配符)

文章目录 Day16 泛型学习目标1 泛型的概念1.1 没有泛型的问题1.2 泛型的引入1.2 泛型的好处1.3 泛型的定义 2 泛型类与泛型接口2.1 使用核心类库中的泛型类/接口案例一&#xff1a;Collection集合相关类型案例二&#xff1a;Comparable接口 2.2 自定义泛型类与泛型接口语法格式…

【成都游戏业:千游研发之都的发展与机遇】

成都游戏业&#xff1a; 千游研发之都的发展与机遇 作为我国西部游戏产业的龙头&#xff0c;成都这座城市正在高速发展&#xff0c;目标是崛起成为千亿级游戏研发之都。多年来&#xff0c;在政策扶持、人才汇聚以及文化底蕴等助力下&#xff0c;成都游戏业已经形成完整的产业链…

matlab代码--基于stbc编码的MIMO-OFDM系统的误码率分析

1 前言 空时分组编码STBC&#xff08;Space Time Block Coding&#xff09;用在无线通信中传输一个数据流的多个拷贝。通过许多天线来产生数据的多种接收版本&#xff0c;提高数据传输的可靠性。接收机接收到的数据拷贝中&#xff0c;存在一些比其它拷贝“更好”的拷贝。而这种…

git中将所有修改的文件上传到暂存区

案例&#xff1a; 我将本地的多个文件进行了修改&#xff0c;导致文件发生了变化。使用git status命令&#xff0c;查看文件的状态&#xff0c;发现有多个文件是modified&#xff0c;即被修改了。 本地文件发生了变化&#xff0c;需要将modified的文件添加到暂存区&#xff0c…

C语言第二十八弹---整数在内存中的存储

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 目录 1、整数在内存中的存储 2、大小端字节序和字节序 2.1、什么是大小端&#xff1f; 2.2、为什么有大小端? 2.3、练习 2.3.1、练习1 2.3.2、练习2 2.…

尾矿库安全监测系统的主要内容和平台

一、背景 尾矿库安全监测系统是保障尾矿库安全运行的重要手段&#xff0c;通过对尾矿库进行实时监测&#xff0c;可以及时发现潜在的安全隐患&#xff0c;为采取相应的措施提供科学依据。通过对变形因素、相关因素及诱因因素信息的相关分析处理&#xff0c;对灾变体的稳定状态…

南卡、韶音、Cleer开放式耳机好用吗?最强开放式耳机大揭秘!

​作为一位经验丰富的开放式耳机用户&#xff0c;我想向大家提个醒&#xff1a;在选择耳机时&#xff0c;千万不要盲目跟风或过于依赖所谓的“网红”或“大牌产品”。毕竟&#xff0c;每个人的需求和使用环境都是独一无二的。选择适合自己的耳机才是最重要的&#xff01; 为了…

Python:Keyboard Interrupt - 当代码遇到“Ctrl+C“时发生了什么?

Python&#xff1a;Keyboard Interrupt - 当代码遇到"CtrlC"时发生了什么&#xff1f; &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;【Matplotlib之旅&#xff1a;零基础精通数据可视化】 &#x1f4a1; 创作高质量博文&#x…

Linux之用户和用户组的深入了解

目录 一、简介 1.1、用户&#xff1a; 1.2、用户组 1.3、UID和GID 1.3、用户账户分类 查看用户类别 超级用户root(0) 程序用户(1~499) 普通用户(500~65535) 二、用户 2.1、添加新的用户账号&#xff1a;useradd 2.2、删除账号&#xff1a;userdel 有-r与没有-r区别…