Vj数据结构实验8(一)

要求

使用线性开型寻址实现

描述

给定散列函数的除数D和操作数m,输出每次操作后的状态。
有以下三种操作:

  1. 插入x,若散列表已存在x,输出“Existed”,否则插入x到散列表中,输出所在的下标。
  2. 查询x,若散列表不含有x,输出“-1”,否则输出x对应下标。
  3. 删除x,若散列表不含有x,输出“Not Found”,否则输出删除x过程中移动元素的个数。

格式

输入格式

第一行两个整数D,m。分别代表散列函数的除数D和操作数m。
接下来m行,每行两个整数opt和x,分别代表操作类型和操作数。
若opt为0,代表插入x。
若opt为1,代表查询x。
若opt为2,代表删除x。

输出格式

按要求输出。

样例1

输入

7 12
1 21
0 1
0 13
0 5
0 23
0 26
0 33
1 33
1 33
1 13
1 5
1 1

输出

-1
1
6
5
2
0
3
3
3
6
5
1

样例二

输入

20 30
0 84
0 15
0 54
2 15
2 84
1 54
2 54
0 89
1 89
0 13
0 48
2 89
0 60
0 24
1 13
0 6
1 24
0 31
2 60
2 48
0 49
0 9
1 6
1 13
0 33
2 49
0 60
1 6
2 9
1 60

输出

4
15
14
0
0
14
0
9
9
13
8
0
0
4
13
6
4
11
0
0
9
10
6
13
14
1
0
6
0
0

限制

1s, 1024KiB for each test case.

    #include <iostream>
    #include <cstdlib>
    using namespace std;
    template<class K, class E>
    class hashTable{
        public:
            ~hashTable(){delete []table;} // 析构函数
            hashTable(int theDivisor = 11); // 构造函数
            int size(){return dSize;} // 返回长度
            pair<K, E>* find(const K&); // 寻找
            void insert(const pair<const K, E>&); // 插入
            void erase(const K& ); // 删除
        protected:
            int search(const K&) const; // 查询
            pair<const K, E>**table; // 散列表
            int divisor; // 散列函数的除数
            int dSize; // 字典中数对的个数
    };

    // 构造函数
    template<class K, class E>
    hashTable<K, E>::hashTable(int Divisor){
        divisor = Divisor;
        dSize = 0;
        // 分配和初始化散列表数组
        table = new pair<const K, E>* [divisor];
        // 将所有桶置空
        for(int i = 0; i < divisor; i++){
            table[i] = NULL;
        }
    }

    // 查询
    template<class K, class E>
    int hashTable<K, E>::search(const K& theKey)const{
        int i = (int)theKey % divisor; // 起始桶
        int j = i; // 从起始桶开始
        do{
            if(table[j] == NULL || table[j]->first == theKey){ // 检测直到桶为空或者遍历一遍
                return j;
            }
            else{
                j = (j + 1) % divisor;
            }
        }while(j != i); // 又回到起始桶
        return j; // 表已经满
    }

    // 寻找
    template<class K, class E>
    pair<K, E> *hashTable<K, E>::find(const K& theKey){
        int b = search(theKey);
        if(table[b] == NULL || table[b]->first != theKey){
            cout << -1 << endl;
            return NULL; // 未找到匹配的数对
        }
        else{
            cout << b << endl;
        }
    }

    // 插入
    template<class K, class E>
    void hashTable<K, E>::insert(const pair<const K, E> &thePair){
        int b = search(thePair.first);
        if(table[b] == NULL){ // 没有找到进行插入
            table[b] = new pair<const K, E>(thePair);
            dSize++;
            cout << b << endl;
        }
        else if(table[b]->first == thePair.first){ // 找到之后进行输出为第几个
            table[b]->second = thePair.second;
            cout << b << endl;
        }
        else{
            cout << "Existed" << endl;
        }
    }

    // 删除
    template<class K, class E>
    void hashTable<K, E>::erase(const K& theKey){
        int b = search(theKey);
        if(table[b] == NULL || table[b]->first != theKey){
            cout << "Not Found" << endl;
        }
        else{
            table[b] = NULL; // 删除
            int n = b, a = b; // 设置删除点,便于遍历
            b = (b+1) % divisor; // 从删除的后一位开始遍历
            int x = 0; // 记录移动个数
            while(table[b]!= NULL && b != n){ // 没有遇到空桶或者没有遍历一遍的话继续执行
                int m = (int)table[b]->first % divisor; // b索引中数字应该在的索引位置
                // 三种情况进行移动
                // 1.空桶在b索引之前,而b索引对应的数字应该在的索引大于b,实现左移一位(循环)
                // 2.b索引小于b中对应数字应该在的索引,且空桶大于等于b中数字应该对应的索引,实现左移一位(循环)
                // 3.b中数字应该对应的索引小于等于空桶且b在空桶之后,实现左移一位
                // 下面表达式可以理解为 
                //  a: 空桶(上一次移动的元素对应的数组索引(第a个桶))
                //  b: 指针指向的数组索引(即第b个桶)  
                //  m: 第b个桶中数字原本应该在的数组索引(原本应该在的第m个桶)
                if((a < b && b < m) || (b < m && m <= a) || (m <= a && a < b)){ 
                    table[a] = table[b];
                    a = b;
                    x++;
                }
                b = (b+1)%divisor; // 指针移动
            }
            table[a] = NULL; // 最后进行删除,使其等于空
            cout << x << endl;
        }
    }
    int main(){
        int D, m;
        cin >> D >> m;
        hashTable<int,int> a(D);
        for(int i = 0; i < m; i++){
            int r, t;
            cin >> r >> t;
            switch(r){
                case 0: {pair<int, int>p(t, 0); a.insert(p);}
                    break;
                case 1: {pair<int, int> *p = a.find(t);}
                    break;
                case 2: a.erase(t);
                    break;
            }
        }
        
        return 0;
    }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值