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

目录

字典是什么

字典线性结构的表述

1.线性表描述

2。跳表描述

3.散列表描述

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

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


字典是什么

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

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

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

字典线性结构的表述

1.线性表描述

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

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

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

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

template <class K ,class V>
class elem{
public:
    K key;V value;
    elem* next=NULL;
    elem(K key, V value) : key(key), value(value){}
};
template <class K ,class V>
class dict{
public:
    int num=0;//初始长度为0;
    elem<K,V>* point=NULL;
    dict<K,V>(){
        cout<<endl;//我的天哪clion的p事情是真的多啊超
        //四个操作1,判断是否为空,2,返回数目,,3,删除数对,,4,增加书堆,,5两种查询
    }
    bool empty(){
        return num;
    }
    V searchValueByKey(K key){
        if(num==0){
            return NULL;
        }else{
            elem<K,V>* temp=point;
            while(temp&&temp->key!=key){temp=temp->next;}
            if(temp){
                return temp->value;
            }else{
                return NULL;
            }
        }
    }
    void add(K key,V value){
        if(searchValueByKey(key)==NULL){
            if(num==0){
                point=new elem<K,V>(key,value);num++;
            }else{
                elem<K,V>* temp=point;
                while(point){point=point->next;}
                point=new elem<K,V>(key,value);num++;
            }
        }else{//如果原来有,那么就进行覆盖
            elem<K,V>* temp= getElementByKey(key);
            temp->value=value;
        }

    }
    void del(){
        if(num==0){
            cout<<"字典中已经没有别的元素了"<<endl;
        }else{
            elem<K,V>* temp=point;
            while(point->next){point=point->next;}
            num--;
        }
    }
    elem<K,V>* getElementByKey(K key){
        if(num==0){
            return NULL;
        }else{
            elem<K,V>* temp=point;
            while(temp&&temp->key!=key){temp=temp->next;}
            if(temp){
                return temp;
            }else{
                return NULL;
            }
        }
    }
    void erase(K key){
        if(searchValueByKey(key)!=NULL){//如果确实有这个点才进行删除
            elem<K,V>* temp=point;
            if(point->key==key){
                point=point->next;delete temp;
            }else{
                while(point->next->key!=key){point=point->next;}
                elem<K,V>* temp2=temp->next;
                temp->next=temp->next->next;
                delete temp2;
            }
        }
    }
};

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

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

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

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值