Vijos数据结构基础C++实验整理(八)——散列表

本文介绍了两种散列表的操作实现,包括直接寻址法和链表法。第一种实现中,散列表使用除留余数法解决冲突,支持插入、查询和删除操作,输出涉及元素下标和移动次数。第二种实现采用链表法,处理冲突时维护有序链表,支持查找元素的链表长度和删除操作后的链表长度。样例展示了各种操作的输出结果。
摘要由CSDN通过智能技术生成

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

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

(二)给定散列函数的除数D和操作数m,输出每次操作后的状态。
有以下三种操作:
5. 插入x,若散列表已存在x,输出"Existed"
6. 查询x,若散列表不含有x,输出"Not Found",否则输出x所在的链表长度
7. 删除x,若散列表不含有x,输出"Delete Failed",否则输出x所在链表删除x后的长度

样例:
(一)
输入:
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
(二)
输入:
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

代码实现(由上至下分别为题目一、题目二的C++代码):

#include <string>
#include <iostream>

using namespace std;

template <class K> class Hash;
template<>
class Hash<int>
{
public:
    size_t operator()(const int theKey) const
    {
        return size_t(theKey);
    }
};

template<class K, class E>
class hashTable
{
public:
    hashTable(int theDivisor = 11);
    ~hashTable() { delete[] table; }

    bool empty() const { return dSize == 0; }
    int size() const { return dSize; }
    pair<const K, E>* find(const K&) const;
    void find2(const K&) const;
    void insert(const pair<const K, E>&);
    void output(ostream& out) const;
    void erase(K&);
    void erase1(K&);
protected:
    int search(const K&) const;
    pair<const K, E>** table;
    Hash<K> hash;
    int dSize;
    int divisor;
};

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
{
    int i = (int)hash(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>::erase1(K& theKey)
{
    int b = search(theKey);
    if (table[b] == NULL || table[b]->first != theKey)
        cout << "Not Found" << endl;
    else
    {
        table[b] = NULL;
        int flag = 0;
        int point = b, m = b, signal;
        do
        {
            point = (point + 1) % divisor;
            if (table[point] == NULL)
                break;
            signal = table[point]->first % divisor;
            if ((signal <= m && m < point) || (point < signal && signal <= m) || (point < signal && m < point))
            {
                table[m] = table[point];
                table[point] = NULL;
                m = point;
                flag++;
            }
        } while (table[(point + 1) % divisor] != NULL && point != b);
        cout << flag << endl;
    }
}

template<class K, class E>
void hashTable<K, E>::erase(K& theKey) {
    int flag = 0;
    int b = search(theKey);

    if (table[b] == NULL) {
        cout << "Not Found" << endl;
        return;
    }

    table[b] = NULL;

    int point = b;//当前的空位置

    int i, t;

    for (i = point;; i++) {//查找N后面NULL之前与d模相同的元素,若有将它移到空位上
        if (table[(i + 1) % divisor] == NULL) {//||(table[(i + 1) % divisor]->first % divisor != point && table[(i + 2) % divisor] == NULL)) {
            break;
        }
        if (table[(i + 1) % divisor]->first % divisor == point) {
            table[point] = table[(i + 1) % divisor];
            flag++;
            table[(i + 1) % divisor] = NULL;

            t = point;
            point = i + 1;
            i = t;
        }
    }


    int c = point;
    int C = c % divisor;
    int C1 = (c + 1) % divisor;
    while (table[C1] != NULL && C1 != (table[C1]->second % divisor)) {//后面NULL之前没有与c模相同的元素,移动。
        table[C] = table[C1];
        table[C1] = NULL;
        c++;
        C = c % divisor;
        C1 = (c + 1) % divisor;
        flag++;
    }
    dSize--;
    cout << flag << endl;
}//停止条件:后面没有模相同的元素而且移动完成   或者   后面有相同的元素

template<class K, class E>
pair<const K, E>* hashTable<K, E>::find(const K& theKey) const
{
    int b = search(theKey);

    if (table[b] == NULL || table[b]->first != theKey)
        return NULL;

    return table[b];
}

template<class K, class E>
void hashTable<K, E>::find2(const K& theKey) const
{
    int b = search(theKey);

    if (table[b] == NULL || table[b]->first != theKey) {
        cout << -1 << endl;
        return;
    }
    cout << b << endl;
    return;
}

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)
        {
            cout << "Existed" << endl;
        }
        else {

        }
    }
}

template<class K, class E>
void hashTable<K, E>::output(ostream& out) const
{
    for (int i = 0; i < divisor; i++)
        if (table[i] == NULL)
            cout << "NULL" << endl;
        else
            cout << table[i]->first << " "
            << table[i]->second << endl;
}

template <class K, class E>
ostream& operator<<(ostream& out, const hashTable<K, E>& x)
{
    x.output(out); return out;
}

int main()
{
    int D, m;
    cin >> D >> m;
    hashTable<int, int> a(D);
    pair<int, int> q;
    for (int i = 0; i < m; i++) {
        int op, number;
        cin >> op >> number;
        if (op == 0) {
            q.first = number; q.second = number;
            a.insert(q);
        }
        else if (op == 1) {
            q.first = number; q.second = number;
            a.find2(q.first);
        }
        else if (op == 3) {
            cout << a << endl;
        }
        else {
            q.first = number; q.second = number;
            a.erase1(q.first);
        }
    }
    return 0;
}

#include <iostream>
#include <string>

using namespace std;
/// <summary>
/// 
/// 
/// 
template <class K> class Hash;



template<>
class Hash<int>
{
public:
    size_t operator()(const int theKey) const
    {
        return size_t(theKey);
    }
};

/// <summary>
/// 
/// 
/// 
template<class K, class E>
class dictionary
{
public:
    virtual ~dictionary() {}
    virtual bool empty() const = 0;
    virtual int size() const = 0;
    virtual pair<const K, E>* find(const K&) const = 0;
    virtual void erase(const K&) = 0;
    virtual void insert(const pair<const K, E>&) = 0;
};
/// <summary>
/// 
/// 
/// 
template <class K, class E>
struct pairNode
{
    typedef pair<const K, E> pairType;
    pairType element;
    pairNode<K, E>* next;

    pairNode(const pairType& thePair) :element(thePair) {}
    pairNode(const pairType& thePair, pairNode<K, E>* theNext)
        :element(thePair) {
        next = theNext;
    }
};
/// <summary>
/// 
/// 
/// 
template<class K, class E>
class sortedChain : public dictionary<K, E>
{
public:
    sortedChain() { firstNode = NULL; dSize = 0; }
    ~sortedChain();

    bool empty() const { return dSize == 0; }
    int size() const { return dSize; }
    pair<const K, E>* find(const K&) const;
    void erase(const K&);
    void insert(const pair<const K, E>&);
    void output(ostream& out) const;

protected:
    pairNode<K, E>* firstNode;
    int dSize;
};

template<class K, class E>
sortedChain<K, E>::~sortedChain()
{
    while (firstNode != NULL)
    {
        pairNode<K, E>* nextNode = firstNode->next;
        delete firstNode;
        firstNode = nextNode;
    }
}

template<class K, class E>
pair<const K, E>* sortedChain<K, E>::find(const K& theKey) const
{
    pairNode<K, E>* currentNode = firstNode;
    while (currentNode != NULL &&
        currentNode->element.first != theKey)
        currentNode = currentNode->next;

    if (currentNode != NULL && currentNode->element.first == theKey) {
        cout << dSize<<endl;
        return &currentNode->element;
    }

    return NULL;
}

template<class K, class E>
void sortedChain<K, E>::insert(const pair<const K, E>& thePair)
{
    pairNode<K, E>* p = firstNode,
        * tp = NULL;
    while (p != NULL && p->element.first < thePair.first)
    {
        tp = p;
        p = p->next;
    }

    if (p != NULL && p->element.first == thePair.first)
    {
        cout << "Existed" << endl;
        //p->element.second = thePair.second;
        return;
    }

    pairNode<K, E>* newNode = new pairNode<K, E>(thePair, p);

    if (tp == NULL) firstNode = newNode;
    else tp->next = newNode;

    dSize++;
    return;
}

template<class K, class E>
void sortedChain<K, E>::erase(const K& theKey)
{
    pairNode<K, E>* p = firstNode,
        * tp = NULL;
    while (p != NULL && p->element.first < theKey)
    {
        tp = p;
        p = p->next;
    }

    if (p != NULL && p->element.first == theKey)
    {
        if (tp == NULL) firstNode = p->next;
        else tp->next = p->next;

        delete p;
        dSize--;
        cout << dSize<<endl;
        return;
    }
    cout << "Delete Failed" << endl;
}

template<class K, class E>
void sortedChain<K, E>::output(ostream& out) const
{
    for (pairNode<K, E>* currentNode = firstNode;
        currentNode != NULL;
        currentNode = currentNode->next)
        out << currentNode->element.first << " "
        << currentNode->element.second << "  ";
}

template <class K, class E>
ostream& operator<<(ostream& out, const sortedChain<K, E>& x)
{
    x.output(out); return out;
}
/// <summary>
/// 
/// 
/// 
template<class K, class E>
class hashChains : public dictionary<K, E>
{
public:
    hashChains(int theDivisor = 11)
    {
        divisor = theDivisor;
        dSize = 0;

        table = new sortedChain<K, E>[divisor];
    }

    ~hashChains() { delete[] table; }

    bool empty() const { return dSize == 0; }
    int size() const { return dSize; }

    pair<const K, E>* find(const K& theKey) const
    {
        return table[hash(theKey) % divisor].find(theKey);
    }
    void find1(const K& theKey) const
    {
        if (table[hash(theKey) % divisor].find(theKey) == NULL) {
            cout << "Not Found" << endl;
        }
        else {

        }
    }

    void insert(const pair<const K, E>& thePair)
    {
        int homeBucket = (int)hash(thePair.first) % divisor;
        int homeSize = table[homeBucket].size();
        table[homeBucket].insert(thePair);
        if (table[homeBucket].size() > homeSize)
            dSize++;
    }

    void erase(const K& theKey)
    {
        table[hash(theKey) % divisor].erase(theKey);
    }

    void output(ostream& out) const
    {
        for (int i = 0; i < divisor; i++)
            if (table[i].size() == 0)
                cout << "NULL" << endl;
            else
                cout << table[i] << endl;
    }


protected:
    sortedChain<K, E>* table;
    Hash<K> hash;
    int dSize;
    int divisor;
};

template <class K, class E>
ostream& operator<<(ostream& out, const hashChains<K, E>& x)
{
    x.output(out); return out;
}


int main()
{
    int D, m;
    cin >> D >> m;
    hashChains<int, int> a(D);
    pair<int, int> q;
    for (int i = 0; i < m; i++) {
        int op, number;
        cin >> op >> number;
        if (op == 0) {
            q.first = number; q.second = number;
            a.insert(q);
        }
        else if (op == 1) {
            q.first = number; q.second = number;
            a.find1(q.first);
        }
        else if (op == 3) {
            cout << a << endl;
        }
        else {
            q.first = number; q.second = number;
            a.erase(q.first);
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值