zoukankan      html  css  js  c++  java
  • 刷题散记

    【1、C malloc】
    result=(int*)malloc(sizeof(int)*2)
    malloc 是 c 语言中的动态分配内存,malloc 函数返回的是 void\* 型,所以要强制类型转换成 int,在前面加上 (int *),才能给整型赋值,后面 (sizeof(int)*2) 的意思是分配两个 int 大小的空间;
    ========
    【2、哈希表】
    哈希表,又名散列表。一种数据结构。
    实现方式:数组+链表 / 数组+二叉树
    本质上是以数组方式存储key-value键值对
    存储方式:key ——》经过哈希/散列函数计算得出哈希值 ——》以哈希值为索引存储键值对
    (在哈希表中,a映射到b,a就叫做键值,b叫做a的哈希值)
    当计算得出的哈希值重复,成为哈希冲突/哈希碰撞
    处理哈希冲突:1、开放寻址法 2、拉链法
    开放寻址法:使用冲突位置的后一位置进行存储,如果也已被占用,则以此类推(如java中的ThreadLocal)
    拉链法:将数组变为链表+数组的存储方式。将冲突键值对存储在已有键值对的后方,使用next指针指向后者,形成一个链表
    <关于拉链法>以java的HashMap为例,若链表元素个数>=8,链表自动转化为树结构,若长度<=6,则转回链表(7作为差值,来避免频繁的进行树和链表的转换)
    哈希表的扩容:若占用率超过增长因子(又名负载因子,即已占用位置和总位置的百分比),比如HashMap增长因子为75%,则触发扩容。
    扩容——新创建一个数组是原来的2倍,然后把原数组的所有键值对都重新Hash一遍放到新的数组。
    哈希表读取:通过Key利用哈希函数得出key的哈希值(即地址),通过哈希值去访问对应链表。若第一个键值对的key值与查询key不符,则查找下一位,直到找到。
    哈希表的核心:哈希函数

    参考文章:https://zhuanlan.zhihu.com/p/95156642

    有关问题:
    1、为什么HashMap不是线程安全的?
    考虑两方面:1.有没有写2.有没有写同一个对象(共享资源)
    看成链表一样,会有多个线程对数据进行修改,在插入的过程包括扩容中是使数据出现错误。
    2、冲突可能消除吗?
    数组的长度 << 数据的个数,所有数据放在有限个数组元素中,必然会发生冲突
    3、冲突不能消除的情况,并且不想要冲突,怎么尽可能避免冲突?
    <1>hash的函数设计:理想情况下,key是符合均匀分布的。经过hash函数,得到的hash值也尽可能的均匀分布。
    <2>负载因子=key的个数/数组的长度。假设数组长度不变,key越多,越容易发生冲突。可通过控制负载因子来控制冲突
    降低负载因子的方法:增加数组的长度(为什么需要扩容:通过增加数组长度,降低负载因子,降低冲突率)
    java中负载因子为什么默认0.75?经过计算+经验值,超多阈值的情况下,冲突率太高了。
    4、真冲突了怎么解决?
    闭散列:此处不留爷,自有留爷处
    开散列/哈希桶: 利用一个其他的数据结构存储所有冲突的key,之所以选择链表是:一般情况下冲突的个数不会太多,链表就够用了。
    单链表每有一个数据就保留一个数据,顺序表是需要预留空间。HashMap是采用这种方式。

    参考文章:https://blog.csdn.net/weixin_45285317/article/details/104483749
    =========
    【3、C++ 中的set、map 和 unordered_set、unordered_map】
    【set和unordered_set区别】
    set基于红黑树实现,红黑树具有自动排序的功能,因此map内部所有的数据,在任何时候,都是有序的。
    (C++11新容器)unordered_set基于哈希表,使用键值对存储,对于冲突采用链地址法,把具有同一关键码的数据组成一个链表。数据插入和查找的时间复杂度很低,几乎是常数时间,而代价是消耗比较多的内存,无自动排序功能。
    【set】
    st.insert(num)
    【map】
    键值对容器,里面的数据成对出现。key只能在map中出现一次。map内部所有的数据按key排序。
    声明:
    1、map<int, string> ID_Name;
    // 使用{}赋值是从c++11开始的,因此编译器版本过低时会报错,如visual studio 2012
    2、map<int, string> ID_Name = { { 2015, "Jim" },{ 2016, "Tom" },{ 2017, "Bob" } };
    插入操作:
    1、[ ]进行单个插入
    // 如果已经存在键值2015,则会作赋值修改操作,如果没有则插入
    ID_Name[2015] = "Tom";
    2、insert进行单个or多个插入(insert共有4个重载函数)
    pair<iterator,bool> insert (const value_type& val);// 插入单个键值对,并返回插入位置和成功标志,插入位置已经存在值时,插入失败
    iterator insert (const_iterator position, const value_type& val);//在指定位置插入,在不同位置插入效率是不一样的,因为涉及到重排
    void insert (InputIterator first, InputIterator last);// 插入多个
    void insert (initializer_list<value_type> il);//c++11开始支持,使用列表插入多个
    3、删除
    // 删除键为bfff指向的元素
    cmap.erase("bfff");
    // 删除迭代器 key所指向的元素
    map<string,int>::iterator key = cmap.find("mykey");
    if(key!=cmap.end()) cmap.erase(key);
    // 删除所有元素
    cmap.erase(cmap.begin(),cmap.end())
    4、map容器的迭代器first、second用法
    例:
    map<string, int> m_stlmap;
    m_stlmap[“xiaomi”] = 88;
    auto mpit = m_stlmap.begin();

    first会得到Map中key的有效值,
    second会得到Map中value的有效值。
    所以
    mpit ->first; // 得到是 string 值是 “xiaomi”
    mpit ->second; //得到是 int 值是 88
    ==========
    【4、C++ 中的vector<int>】
    向量(Vector)是一个封装了动态大小数组的顺序容器。可以简单的认为,向量是一个能够存放任意类型的动态数组。
    【vector<int> a 和 int a[]的区别】
    数组使用前要实例化,实例化了,长度就固定了,而Vector实例化不会固定长度,想添加还可以添加内容
    vector<int>不需要动态new内存,当然也不用delete

    1、初始化
    std::vector<std::wstring> v1; //创建一个空的wstring类型的vector
    std::vector<std::wstring> v2(3, L"c"); //创建一个容量为3,全部初始化L"c"
    std::vector<int> v3(5); //创建容量为5,数据类型为int的vector
    std::vector<int> v4(v3); //创建一个从v3拷贝过来的vector
    2、插入元素
    vector<int> vec;
    vec.push_back("3"); //在末尾插入一个元素
    或 vec.insert(vec.end(), "3"); // 在末尾插入一个元素
    vec.insert(vec.begin(), "3"); // 在开头插入一个元素
    vec.insert(vec.begin()+4, "3"); // 在指定位置,例如在第五个元素前插入一个元素
    3、删除
    vec.erase(vec.begin()); //删除开头的元素
    vec.erase(pos) // 删除pos位置的数据,传回下一个数据的位置。
    vec.erase(vec.begin(),vec.end); //删除[begin,end]区间的元素,传回下一个数据的位置。
    vec.pop_back(); //删除最后一个元素
    4、查找
    vector本身没有find方法,需要使用std::find
    vector<int> vec;
    vector<int>::iterator it = find(vec.begin(), vec.end(), 6);
    if (it != vec.end()) return "找到了!";
    else return "没找到!";
    5、其他函数
    vec.front() // 传回第一个数据。
    vec.begin() // 传回迭代器中的第一个数据地址。
    vec.end()-1 // 是vec的最后一个元素,
    vec.end() // 是最后一个元素的后面一位。
    vec.empty() // 判断容器是否为空。
    vec.at(idx) // 传回索引idx所指的数据,如果idx越界,抛出out_of_range。
    vec.size() // 获取nums数组长度
    vec.count(值) // 统计某个指定的值出现次数
    ---
    6、关于字符数组
    vector<string>& strs = [];
    if(strs.empty()) return string(); // *string() 返回空值
    ==========
    【5、关于C++ 中string类型】
    1、获取字符串元素(可使用下标访问string)
    str[index] 或 str.at(index)

    2、字符串查找
    str.find(s1) //查找str中第一次出现s1的位置,并返回(包括0)
    str.rfind(s1) //查找str中最后次出现s1的位置,并返回(包括0)
    s.find_first_of(s1) //查找在s1中任意一个字符在s中第一次出现的位置,并返回(包括0)
    s.find_last_of(s1) //查找在s1中任意一个字符在s中最后一次出现的位置,并返回(包括0)
    s.fin_first_not_of(s1) //查找s中第一个不属于s1中的字符的位置,并返回(包括0)
    s.fin_last_not_of(s1) //查找s中最后一个不属于s1中的字符的位置,并返回(包括0)
    ※※ 查找字符串a是否包含子串b,不是用strA.find(strB) > 0而是strA.find(strB) != string:npos
    string::size_type pos = strA.find(strB);
    if(pos != string::npos){
    // 代码块
    }
    3、字符串截取
    str.substr(pos, n) //截取str中从pos开始(包括0)的n个字符的子串,并返回
    str.substr(pos) //截取str中从从pos开始(包括0)到末尾的所有字符的子串,并返回
    str.replace(pos, n, s1) //替换:用s1替换str中从pos开始(包括0)的n个字符的子串
    reverse(str.begin(), str.end()); //逆序:C++标准类库函数reverse。str执行完这句,就已经是逆序结果。
    string stringStr = std::to_string(intNum) int转string(std::可以省略)
    4、字符串替换
    s.replace(pos, n, s1) //用s1替换s中从pos开始(包括0)的n个字符的子串
    5、数字与字符串互转
    // 数字转字符串
    string str = to_string(x);
    // 字符串转数字
    string str = "7";
    int num = stoi(str);
    7、"str.find(i) != str.end()"和"str.find(i) = str.end()"到底啥意思
    标准库里迭代器部分的内容。即用find函数,去找str这个序列中的i元素,元素不存在,就会返回end()。
    str.find(i) != str.end() //说明找到了
    str.find(i) == str.end() //说明没到
    ==========
    【6、C++ char* 和 char区别】
    1、储存内容不同:char*是定义一个字符串,存储的是一段如“abcd”的数据,而且最后还有一个结束符'\0';char 是定义一个字符,存储一个字符,占一个字节。
    2、数据类型不同:char*是指针类型,是一个用来保存一个内存地址的计算机语言中的变量。char 是字符类型,用来存储字符值。
    ==========
    【7、c++ stack栈】
    栈(Stack)是一种线性存储结构,先进后出(First In Last Out),只能在栈顶进行插入和删除操作。
    stack<char> st;
    st.push('a') // 入栈
    st.pop() // 出栈,删除栈顶元素。
    st.top() // 返回栈顶元素, 但不删除该元素
    st.empty() // 如果栈为空则返回true, 否则返回false;
    st.size(); // 返回栈中元素的个数
    ==========
    【8、cout<<" "与cout<<' '有什么区别】
    cout<<" "表示输出字符串变量值。
    cout<<' '表示是字符变量值,字母的本质也是数字。
    如:
    int a=10;
    cout<<"a";//输出为 字符a;
    cout<<a;//输出为10;
    cout<<'a' ;//输出为65;
    * cout << var << endl; // endl的作用:输出一个换行符,并立即刷新缓冲区
    ==========
    【9、count 和 count_if用法】
    1)count(first,last,value):first是容器的首迭代器,last是容器的末迭代器,value是询问的元素,整个函数返回int型。count函数的功能是:统计容器中等于value元素的个数。
    2)count_if(first,last,comp) (在comp=true的情况下计数) 
    或者 count_if(first,last,value,comp)(这个是在comp=true的情况下统计容器中等于value的元素):
    first为首迭代器,last为末迭代器,value为要查询的元素,comp为比较bool函数,为true则计数,函数返回型是int。
    【统计字符串中某个字符的个数?】
    方法一:count(str.begin(), str.end(), 'a'); // 查找str中字符a的个数

    count_if(list.begin(),list.end(),判断条件,int 返回个数)
    count(list.begin(),list.end(),满足条件的参数,int 返回个数)
    ==========
    【C++ 中的循环】
    1、switch循环
    switch case()的case传参不可以传string类型
    2、foreach循环
    vector<int> nums;
    for(int x: nums){
    // 代码块
    }
    ==========

  • 相关阅读:
    kubernetes入门之kube-proxy实现原理
    kubernetes源码阅读及编译
    docker的网络-Container network interface(CNI)与Container network model(CNM)
    kubernetes入门之skydns
    浅析flannel与docker结合的机制和原理
    kubernetes入门之快速部署
    python并发获取snmp信息及性能测试
    Facebook开源的基于SQL的操作系统检测和监控框架:osquery daemon详解
    Facebook开源的基于SQL的操作系统检测和监控框架:osquery Table详解
    视频工具类产品是个什么玩意,产品经理怎么构思一款视频工具类产品
  • 原文地址:https://www.cnblogs.com/Yan3399/p/15728557.html
Copyright © 2011-2022 走看看