山东大学数据结构实验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>

using namespace std;

template<class K, class E>
class hashTable {
public:
    hashTable(int theDivisor = 11);

    void find(const K &) const;

//返回关键字theKey匹配的数对的指针,若不存在匹配的数对,则返回NULL
    void insert( const pair<const K, E>&);

//在字典中插入一个数对thePair,若存在关键字相同的数对,则覆盖
   void erase(const K &theKey);

    int search(const K& theKey) const;


protected:


    pair<const K, E> **table; // 散列表
    int divisor; // 散列函数的除数
    int dSize; // 字典中数对的个数
};

template<class K, class E>
hashTable<K,E>::hashTable(int theDivisor)
{// 构造函数
    divisor = theDivisor;
    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
{// 搜索一个公开地址散列表,查找关键字为theKey的数对
// 如果匹配的数对存在,则返回它的位置
// 否则返回关键字为theKey的数对可以插入的位置
    int i =(int) theKey % divisor; // 起始桶
    int j = i; // 从起始桶处开始
    do {
        if (table[j]==NULL || table[j]->first == theKey) return j;
        j = (j + 1) % divisor; // 下一个桶
    } while (j != i); // 又返回起始桶?
    return j; // 表已经满
}

template<class K, class E>
void hashTable<K,E>::find(const K& theKey) const
{//返回关键字theKey匹配的数对的指针
//若不存在匹配的数对,则返回NULL
//搜索散列表
    int b = search(theKey);
//判断table[b]是否是匹配数对
    if (table[b] ==NULL || table[b]->first != theKey)
      cout<<-1<<endl;//未找到匹配数对
    else cout<<b<<endl; //找到匹配数对
}
template<class K, class E>
void hashTable<K,E>::insert( const pair<const K, E>& thePair)
{//在字典中插入一个数对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 )
    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索引中数字应该在的索引位置
            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 op, x;
        cin >> op >> x;
        switch(op){
            case 0: { pair<int, int>p(x, 0);a.insert(p);}
                break;
            case 1: { a.find(x);}
                break;
            case 2: a.erase(x);
                break;
        }
    }

    return 0;
}

要求

使用链表散列方式

描述

给定散列函数的除数D和操作数m,输出每次操作后的状态。

有以下三种操作:

  1. 插入x,若散列表已存在x,输出"Existed"
  2. 查询x,若散列表不含有x,输出"Not Found",否则输出x所在的链表长度
  3. 删除x,若散列表不含有x,输出"Delete Failed",否则输出x所在链表删除x后的长度

格式

输入格式

第一行两个整数D(1<=D<=3000)和m(1<=m<=3000),其中D为散列函数的除数,m为操作数。

接下来的m行,每行两个整数opt和x,分别代表操作类型和操作数。

若opt为0,则代表向散列表中插入x;
若opt为1,代表查询散列表中x是否存在;
若opt为2,(如果散列表中含有x),删除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

样例输出

    Not Found
    3
    3
    1
    3
    1

样例2

样例输入

    7 15
    2 10
    0 10
    0 10
    2 10
    1 10
    0 10
    1 10
    0 17
    0 2
    0 16
    0 11
    2 2
    2 10
    1 11
    1 17

样例输出

    Delete Failed
    Existed
    0
    Not Found
    1
    1
    1
    1
    1

数据范围

对于前60%的数据,只包含插入和查询操作
对于后40%的数据,包含插入、查询与删除操作

#include <iostream>

using namespace std;

struct Node {
    int element;
    Node *next;

    Node(int theElement) {
        element = theElement;
    }
};

class linearListHashtable {
public:
    linearListHashtable() {
        firstNode = NULL;
        size = 0;
    }

    ~linearListHashtable();

    void insert(int element);

    void find(int element);

    void erase(int element);


private:
    Node *firstNode;
    int size;

};

void linearListHashtable::insert(int element) {
    int flag = 0;
    Node *cur = firstNode;
    if(cur==NULL){firstNode=new Node(element);size++;firstNode->next=NULL;return ;}
    while (cur->next !=NULL ) {
        if (element == cur->element) {
            cout << "Existed" << endl;
            flag = 1;
            break;
        }
        cur = cur->next;
    }
    if(cur->element==element&&flag==0){cout<<"Existed"<<endl;flag=1;}
    if (flag != 1)
    {cur->next = new Node(element);
    size++;
    cur->next->next=NULL;}
}

void linearListHashtable::find(int element) {
    int flag = 0;
    Node *cur = firstNode;
    if(firstNode==NULL){cout << "Not Found" << endl;return ;}
    while (cur ->next!=NULL ) {
        if (element == cur->element) {
            cout << size << endl;
            flag = 1;
            break;
        }
        cur = cur->next;
    }if(cur->element==element&&flag==0){
        cout<<size<<endl;
        flag=1;
    }
    if (flag == 0)
        cout << "Not Found" << endl;
}

void linearListHashtable::erase(int element) {
    int flag = 0;
    if(firstNode==NULL){cout << "Delete Failed" << endl;return;}
    int Element=firstNode->element;
    if (firstNode->element == element) {
        firstNode = firstNode->next;
        size--;
        cout << size  << endl;
        return;
    }
    Node *cur = firstNode->next;
    Node *pre = firstNode;
    while (cur !=NULL ) {
        if (element == cur->element) {
            pre->next = pre->next->next;
            size--;
            cout << size<<endl;
            flag = 1;
            break;
        }
        cur = cur->next;
        pre = pre->next;
    }
    if (flag == 0)
        cout << "Delete Failed" << endl;

}


int main() {
    int D, m;
    cin >> D>>m;
    linearListHashtable *a = new linearListHashtable[D];
    int opt;
    int value = 0, index = 0;
    while (m--) {
        cin >> opt;
        switch (opt) {
            case 0: {
                cin >> value;
                index = value % D;
                a[index].insert(value);
            }
                break;
            case 1: {
                cin >> value;
                index = value % D;
                a[index].find(value);

            }
                break;
            case 2: {
                cin>>value;
                index =value % D;
                a[index].erase(value);

            }
                break;


        }


    }
return 0;

}
posted @   Lyz103  阅读(233)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示