散列表(下)——分离链接法

概述

在我的上一篇博客散列表(上)——开放定址法 主要讲述了开放定址法的三种思路:线性探测法,平法探测法,双散列法三种思路,以及线性探测的代码实现。在这篇博客里,主要讲解第二中解决冲突的办法——分离链接法。


分离链接法

分离链接法的思想就是:将相应位置上冲突的所有关键词存储在同一个单链表中。主要办法是,构造以所有可能地址的为头的单链表数组。对于单链表的相关操作已经在之前的博客详细讲述了,如有需要请移步我之前的博客——单链表
全部代码如下:

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

struct node{
    int data;
    struct node* next;  
};

typedef struct node Node;

class HashTable{
    private:
        vector<Node*> nodes;
        int length;
        int Max_Prime; 
    public:
        //构造函数
        HashTable(int length){
            this->length = length;
            nodes.reserve(this->length);
            this->Max_Prime = this->getMaxPrime();
            for(int i = 0 ; i < this->length ; i++){
                this->nodes.push_back(this->Create_Node(i));
            }
        }

        Node* Create_Node(int num){
            Node* node = new Node;
            node->data = num;
            node->next = NULL;
            return node;
        }

        //判断素数函数 
        bool isPrime(int num){
            bool flag = true;
            if(num <= 1){
                flag = false;
            }else if( num == 2){
                flag = true;
            }else{
                for(int i = 2 ; i < num-1 ; i++){
                    //num能被i整除 
                    if(num % i == 0){
                        flag = false;
                        break; 
                    }
                }
            }
            return flag;
        }

        //寻求小于表长的最大素数
        int getMaxPrime(){
            for(int i = this->length-1 ; i >= 0 ; i--){
                if(this->isPrime(i)){
                    return i;
                }
            }
        }

        //hash函数
        int hash(int num){
            return num % this->Max_Prime;
        }

        Node* Attach(Node* node1 ,Node* node2){
            Node* cur = node1;
            while(1){
                if(cur->next == NULL){
                    cur->next = node2;
                    break;
                }
                cur = cur->next;
            }
            return node1;
        }

        //插入函数 
        void Insert(int num){
            //计算结点所在的地址 
            int index = this->hash(num);
            //建立结点 
            Node* node = NULL;
            node = this->Create_Node(num); 
            //把结点连接到合适的地址结点上 
            Node* tmp = NULL;
            tmp = this->nodes[index];
            this->nodes[index] = this->Attach(tmp,node);
        } 

        //建表函数
        void Create(int size,int* num){
            for(int i = 0 ; i < size ; i++){
                //插入结点
                this->Insert(num[i]);
            }
        }

        //删除结点
        bool Delete(int num){
            int index = this->hash(num);
            Node* cur = this->nodes[index];
            while(cur->next->data != num){
                cur = cur->next;
            }
            if(cur == NULL){//在哈希表中未找到num 
                return false;
            }
            Node* tmp = cur->next;
            cur->next = cur->next->next;
            delete tmp;
            return true; 
        }

        void Print_List(Node* node){
            Node* cur = node;
            while(cur){
                cout<<cur->data<<" ";
                cur = cur->next; 
            }
        }

        //查找函数 
        int Find(int num){
            int index = this->hash(num);
            Node* cur = this->nodes[index];
            while(cur->data != num){
                cur = cur->next;
            }
            if(cur == NULL){//哈希表中没有num 
                index = -1;
            }
            return index;
        }

        //打印函数
        void Print(){
            cout<<"下标\t元素:"<<endl;
            for(int i = 0 ; i < this->nodes.size() ; i++){
                if(this->nodes[i]->next != NULL){
                    cout<<i<<":\t";
                    this->Print_List(this->nodes[i]->next);
                    cout<<endl; 
                }
            }
        } 
};

int main()
{
    cout<<"请输入哈希表长度:"<<endl;
    int length;
    cin>>length;
    cout<<"请输入需要插入的元素个数:"<<endl;
    int size;
    int* data;
    cin>>size;
    data = new int[size];
    cout<<"请初始化元素:"<<endl;
    for(int i = 0 ; i < size ; i++){
        cin>>data[i];
    }

    HashTable hashtable(length); 
    hashtable.Create(size,data);
    cout<<"哈希表为:"<<endl;
    hashtable.Print();

    int num,index;
    cout<<"请输入要寻找的元素:"<<endl;
    cin>>num;
    index = hashtable.Find(num);
    if(index == -1){
        cout<<"哈希表中没有"<<num<<"这个元素"<<endl; 
    }else{
        cout<<num<<"在地址为"<<index<<"所指向的链表里"<<endl; 
    }

    cout<<"请输入要插入的元素:"<<endl;
    cin>>num;
    cout<<"插入前哈希表为:"<<endl;
    hashtable.Print(); 
    cout<<"插入后哈希表为:"<<endl;
    hashtable.Insert(num);
    hashtable.Print();

    cout<<"请输入要删除的元素:"<<endl;
    cin>>num;
    cout<<"删除前哈希表为:"<<endl;
    hashtable.Print(); 
    cout<<"删除后哈希表为:"<<endl;
    hashtable.Delete(num);
    hashtable.Print();

    return 0;
 } 

截图:
这里写图片描述
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

daipuweiai

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

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

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

打赏作者

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

抵扣说明:

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

余额充值