实验8.2 链表散列

文章详细描述了如何使用链表散列来处理插入、查询和删除操作。通过定义链节点、创建链表结构以及实现相关函数,实现了基于链表的哈希表。文章提供了具体的函数实现,如find、insert和erase,用于在给定散列函数的除数D和操作数m的条件下,处理各种操作。
摘要由CSDN通过智能技术生成

实验8.2 链表散列

要求

使用链表散列方式

描述

给定散列函数的除数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。

数据保证散列表不会溢出。

输出格式

按需输出。

思路与探讨

散列表线性探查

笔记补充——第十章:散列表,指路10.3 && 10.5.4

整体思路描述

  • 主要是字典的链式描述,包括定义链节点,创建链表结构,实现插入,查询,删除等函数定义与实现。最后基于链表结构创建哈希,实现链式散列。在这里插入图片描述

细节思路描述

sortedChain部分

方法find

查询theKey,若散列表不含有theKey,输出"Not Found",否则输出theKey所在的链表长度

在这里插入图片描述

  • 从第一个节点开始扫描节点,直到遇到第一个关键字大于等于theKey的节点currentNode或全部判断完为止

  • 判断currentNode所指节点中数对的关键字是否等于theKey

    currentNode->element.first =theKey

  • 若相等,输出theKey所在的链表长度,否则返回Not Found

方法insert

插入x,若散列表已存在x,输出"Existed"

  • 从第一个节点开始,寻找第一个关键字≥theKey的数对

  • p->element.first == theKey在这里插入图片描述

  • p->element.first > theKey在这里插入图片描述

    • 新节点newNode ←(插入的数对thePair,p)

      • tp不为空:新节点插入到tp后面tp->next= newNode

      • tp为空:新节点为首节点firstNode=newNode

    • dSize++

方法erase

删除x,若散列表不含有x,输出"Delete Failed",否则输出x所在链表删除x后的长度

在这里插入图片描述

hashChains部分

查找(find):

  • 计算起始桶号为f(k) = k % D;搜索该桶所对应的链表.

    table[hash(theKey) % divisor].find(theKey);
    

插入(insert):

  • 计算f(k);搜索;插入。 关注size判断。

    int homeBucket = (int)hash(thePair.first) % divisor;
    int homeSize = table[homeBucket].size();
    table[homeBucket].insert(thePair);
    if (table[homeBucket].size() > homeSize)
    	dSize++;
    

删除(erase):

  • 计算f(k);搜索;删除

    table[hash(theKey) % divisor].erase(theKey);
    

若已看懂思路,试着自己写~


实现代码

#include <iostream>
#include <string>
using namespace std;

template <class K> class Hash;
template<>
class Hash<int>
{//把类型k映射到一个非负整数
	public:
	    size_t operator()(const int theKey) const
	    {
        	return size_t(theKey);
    	}
};

template<class K, class E>
class dictionary
{
	public:
	    virtual ~dictionary() {}
	    //返回true,当且仅当字典为空
	    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;
};
 
template <class K, class E>
struct pairNode
{
    pair<const K, E> element;
    pairNode<K, E>* next;
    pairNode(const pair<const K, E>& thePair):element(thePair){}
    pairNode(const pair<const K, E>& thePair,pairNode<K, E>* theNext):element(thePair) 
    {next = theNext;}
};

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; }
    	//查询x,若散列表不含有x,输出"Not Found",否则输出x所在的链表长度
        pair<const K, E>* find(const K& theKey) const;
    	//插入x,若散列表已存在x,输出"Existed"
        void insert(const pair<const K, E>& thePair);
        //删除x,若散列表不含有x,输出"Delete Failed",否则输出x所在链表删除x后的长度
        void erase(const K& theKey);
    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;
    //搜索关键字为theKey的数对
    while (currentNode != NULL &&currentNode->element.first != theKey)
        currentNode = currentNode->next;
	//判断是否匹配,若有找到输出x所在的链表长度 
    if (currentNode != NULL && currentNode->element.first == theKey) 
	{
        cout << dSize <<endl;
    }
    //无匹配的数对,输出Not Found 
    else
    {
    	cout<<"Not Found"<<endl;
	}
	
}

template<class K, class E>
void sortedChain<K, E>::insert(const pair<const K, E>& thePair)
{//往字典中插入thePair,覆盖已经存在的匹配的数对
    pairNode<K, E>* p = firstNode, * tp = NULL;//跟踪p
    while (p != NULL && p->element.first < thePair.first)
    {
        tp = p;
        p = p->next;
    }

	//检查是否有匹配的数对
    //情况(1)有匹配的数对
    if (p != NULL && p->element.first == thePair.first)
    {//有就输出Existed
        cout << "Existed" << endl;
        return;
    }
	
	//情况(2)无匹配的数对,为thePair建立新节点
    pairNode<K, E>* newNode = new pairNode<K, E>(thePair, p);
	//在tp之后插入新节点
    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;
    //搜索关键字为theKey的数对
    while (p != NULL && p->element.first < theKey)
    {
        tp = p;
        p = p->next;
    }//tp就是追踪用的,刚好在p的前一个

	//确定是否匹配
    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;
    }
    //没找到就输出"Delete Failed" 
    cout << "Delete Failed" << endl;
}

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
	    {//查找 
	        table[hash(theKey) % divisor].find(theKey);
	    }
					  
	    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);
	    }
	
	protected:
	    sortedChain<K, E>* table;
	    Hash<K> hash;
	    int dSize;
	    int divisor;
};


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 opt, number;
        cin >> opt >> number;
        if (opt == 0) 
		{
            q.first = number; q.second = number;
            a.insert(q);
        }
        else if (opt == 1) 
		{
            q.first = number; q.second = number;
            a.find(q.first);
        } 
		else                      
		{
            q.first = number; q.second = number;
            a.erase(q.first);
    	}
    }
    return 0;
}                       
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啦啦右一

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值