• 【数据结构】关于字典之类的东西


    目录

    字典是什么

    字典线性结构的表述

    1.线性表描述

    2。跳表描述

    3.散列表描述

    线性探查:找有空的地方插入,不过会造成查询的麻烦

    链式散列:每个桶都是一个链表,一旦发生了冲突,就扔到这个链表里


    字典是什么

    (天知道他是什么 只能说这东西见到的讲解都讲得好烂啊,为了考试就以郭老师为准了,,,,我有什么办法嘛,我也想好好学的)

    在java里面有一个叫做map的数据类型,映射其实就是一种hashing字典,字典中的数据是成对存在的,分为key和value。一般来说,查询key,就可以对应找到value。

    常用的操作,查询,增加,删除,一般是根据key进行操作的,key一般是唯一的

    字典线性结构的表述

    1.线性表描述

    线性表描述的特点无非就是,遍历呗,常见的是数组描述法和链表描述法

    数组描述的复杂度为:折半搜索(logn)增加(n)删除(n)

    链表描述的复杂度为:遍历搜索(n)     增加(1) 删除(n)

    以下为链表描述法的具体实现

    1. template <class K ,class V>
    2. class elem{
    3. public:
    4. K key;V value;
    5. elem* next=NULL;
    6. elem(K key, V value) : key(key), value(value){}
    7. };
    8. template <class K ,class V>
    9. class dict{
    10. public:
    11. int num=0;//初始长度为0
    12. elem<K,V>* point=NULL;
    13. dict<K,V>(){
    14. cout<<endl;//我的天哪clion的p事情是真的多啊超
    15. //四个操作1,判断是否为空,2,返回数目,,3,删除数对,,4,增加书堆,,5两种查询
    16. }
    17. bool empty(){
    18. return num;
    19. }
    20. V searchValueByKey(K key){
    21. if(num==0){
    22. return NULL;
    23. }else{
    24. elem<K,V>* temp=point;
    25. while(temp&&temp->key!=key){temp=temp->next;}
    26. if(temp){
    27. return temp->value;
    28. }else{
    29. return NULL;
    30. }
    31. }
    32. }
    33. void add(K key,V value){
    34. if(searchValueByKey(key)==NULL){
    35. if(num==0){
    36. point=new elem<K,V>(key,value);num++;
    37. }else{
    38. elem<K,V>* temp=point;
    39. while(point){point=point->next;}
    40. point=new elem<K,V>(key,value);num++;
    41. }
    42. }else{//如果原来有,那么就进行覆盖
    43. elem<K,V>* temp= getElementByKey(key);
    44. temp->value=value;
    45. }
    46. }
    47. void del(){
    48. if(num==0){
    49. cout<<"字典中已经没有别的元素了"<<endl;
    50. }else{
    51. elem<K,V>* temp=point;
    52. while(point->next){point=point->next;}
    53. num--;
    54. }
    55. }
    56. elem<K,V>* getElementByKey(K key){
    57. if(num==0){
    58. return NULL;
    59. }else{
    60. elem<K,V>* temp=point;
    61. while(temp&&temp->key!=key){temp=temp->next;}
    62. if(temp){
    63. return temp;
    64. }else{
    65. return NULL;
    66. }
    67. }
    68. }
    69. void erase(K key){
    70. if(searchValueByKey(key)!=NULL){//如果确实有这个点才进行删除
    71. elem<K,V>* temp=point;
    72. if(point->key==key){
    73. point=point->next;delete temp;
    74. }else{
    75. while(point->next->key!=key){point=point->next;}
    76. elem<K,V>* temp2=temp->next;
    77. temp->next=temp->next->next;
    78. delete temp2;
    79. }
    80. }
    81. }
    82. };

    2。跳表描述

    跳表感觉是真的怪啊,分成多级跳表,类似在链表中加入折半查找key的编址地点,让搜索的复杂度变成logn,再加上删除增加本来的复杂度为1,所以

    跳表的三个基本操作复杂度,均为logn

    跳表的缺点:分配级和删除的时候难度都很大,所以一般没有哪个一眼顶真想不开写这东西

    查询:跳表本质上是对链表进行折半模拟,因为正常来说,链表虽然具有更快的增删速度,但是碰上查询就直接歇菜了。数组查询某

    个位置的复杂度仅仅是o(1),链表可能要到on。所以跳表就是加上一个索引,使用类似蛙跳的方式进行查询,最终也可以达到类似折半搜索的效果

    (注意,原理不是折半而是蛙跳)

     跳表一般分为多层,每一层的索引数目都是下一层的一半(向上取整)。第一层被称作0级链表。

    平均下来每个元素的查询时间复杂度为logn

    插入的话,我们需要确定从那一层开始改变索引,假如一共有k层,我们就执行k次的抛硬币判断,然后硬币向上的k次结果,就代表我们在k---1层的链表上都进行插入,平均复杂度仍然为logn

    比如这上面的图我们恰好k=2,那就是每一层都添加索引

    至于删除,就是把这个数据的每一层的索引都进行删除 

    3.散列表描述

    散列表利用散列函数f(k),把原本的关键字key变成一个f(key),存table中,table一般是类似数组的那种东西,搜索的复杂度为1.

    举个例子:java中的map差不多,map底层利用的是一个手动长度可变数组+每个桶都是一个链表的方式进行存储的

    散列函数有很多,常见的散列函数是mod n

    理想的散列表中,不会发生溢出,所以最理想的情况下,增删改查的复杂度都是1

    但是散列表一般不会很理想,绝大多数时候,散列函数是无法保证完整的一对一映射,所以溢出的两种处理方式为

    线性探查:找有空的地方插入,不过会造成查询的麻烦

    链式散列:每个桶都是一个链表,一旦发生了冲突,就扔到这个链表里

  • 相关阅读:
    Java中Integer的最大值和最小值
    9.4 RetLibc实战之利用VirtualAlloc
    SQL Developer中执行批量SQL语句
    接口幂等问题:redis分布式锁解决方案
    ZYNQ使用AXI4-HP接口总线读取DDR中的数据
    【pytest】 参数化@pytest.mark.parametrize
    六月集训(第30天) —— 拓扑排序
    51单片机复位电容计算与分析(附带Proteus电路图)
    微信最新更新隐私策略(2023-08-15)
    计算机毕业设计JAVAOA办公系统mybatis+源码+调试部署+系统+数据库+lw
  • 原文地址:https://blog.csdn.net/weixin_62697030/article/details/127952353