• 散列查找-平方探测法


    • 解决散列表的冲突问题有两种办法:开放地址法和链地址法

    下面的代码是采用开放地址法,平方探测时的代码。

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <stdbool.h>
    
    #define MAXTABLESIZE 100
    
    typedef int ElementType;
    
    //散列单元状态类型
    typedef enum
    {
        Legitimate,  //有合法元素
    	Empty, //空单元
    	Deleted  //有已删除元素
    }EntryType;
    
    struct HashEntry  //散列表的单元类型
    {
    	ElementType Data;  //存放元素
    	EntryType Info;  //单元状态
    };
    
    struct TblNode  //散列表的节点定义
    {
    	int TableSize;  //表的最大长度
    	struct HashEntry* Cells;  //存放散列单元数据的数组
    };
    
    //返回大于N且不超过MAXTABLESIZE的素数
    int NextPrime(int N)
    {
    	int i;
    	int p = (N % 2) ? N + 2 : N + 1;  //从大于N的下一个奇数开始
    
    	while (p <= MAXTABLESIZE)
    	{
    		for (i = (int)sqrt(p); i > 2; i--)
    		{
    			if (!(p % i))
    			{
    				break;  //p不是素数
    			}
    		}
    		if (i == 2)
    		{
    			break;
    		}
    		else
    		{
    			p = p + 2;
    		}
    		
    	}
    
    	return p;
    }
    
    struct TblNode* CreateTable(int TableSize)
    {
    	struct TblNode* Hash;
    	int i;
    
    	Hash = (struct TblNode*)malloc(sizeof(struct TblNode));
    	Hash->TableSize = NextPrime(TableSize);  //保证散列表的最大长度是一个素数
    	//声明单元组
    	Hash->Cells = (struct HashEntry*)malloc(Hash->TableSize * sizeof(struct HashEntry));
    	//初始化单元状态为空单元
    	for (int i = 0;i < Hash->TableSize;i++)
    	{
    		Hash->Cells[i].Info = Empty;
    	}
    
    	return Hash;
    }
    
    int GetHashPos(ElementType Key,int TableSize)
    {
    	return Key % 11;
    }
    //
    int Find(struct TblNode* Hash,ElementType Key)
    {
    	int CurrentPos;
    	int NewPos;
    	int CNum = 0;  //记录冲突次数
    
    	NewPos = CurrentPos = GetHashPos(Key,Hash->TableSize);  //初始散列位置
    
    	while (Hash->Cells[NewPos].Info != Empty &&
    		   Hash->Cells[NewPos].Data != Key)
    	{
    		//统计1次冲突 并判断奇偶次
    		if (++CNum % 2)  //奇数次冲突
    		{
    			//增量为 +[(CNum+1)/2]^2
    			NewPos = CurrentPos + (CNum + 1) * (CNum + 1) / 4;
    			if (NewPos >= Hash->TableSize)
    			{
    				NewPos = NewPos % Hash->TableSize;  //调整为合法地址
    			}
    		}
    		else  //偶数次冲突
    		{ 
    			NewPos = CurrentPos - CNum * CNum / 4;
    			while (NewPos < 0)
    			{
    				NewPos = NewPos + Hash->TableSize;  //调整为合法地址
    			}
    		}
    	}
    	//此时NewPos或者是Key的位置,或者是一个空单元的位置(表示找不到)
    	return NewPos;
    }
    //将元素插入哈希表
    bool Insert(struct TblNode* Hash,ElementType Key)
    {
    	int  pos = Find(Hash,Key);
    
    	if (Hash->Cells[pos].Info != Legitimate)
    	{
    		//如果这个单元格没有被占,说明key可以插入在此
    		Hash->Cells[pos].Data = Key;
    		Hash->Cells[pos].Info = Legitimate;
    		return true;
    	}
    	else
    	{
    		printf("键值已存在.
    ");
    		return false;
    	}
    
    }
    
    int main()
    {
    	int a[] = {47,7,29,11,9,84,54,20,30};
    	//这里传入的值是9,但创建的HashTable的size并不是9,而是11
    	struct TblNode* HashTable = CreateTable(9);
    
    	for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
    	{
    		if (!Insert(HashTable, a[i]))
    		{
    			printf("插入元素失败.
    ");
    		}
    	}
    	printf("插入元素成功.
    ");
    	//访问元素
    	for (int i = 0; i < HashTable->TableSize; i++)
    	{
    		if (HashTable->Cells[i].Info == Legitimate)
    		{
    			printf("%d  %d.
    ", i, HashTable->Cells[i].Data);
    		}
    	}
    	system("pause");
    	return 0;
    }
    
    
    • 运行结果

    • 参考资料
      1 《数据结构(第2版)》 陈越主编 高等教育出版社
  • 相关阅读:
    MQTT Server搭建(apache-apollo)和MQtt Client搭建
    playbook 包含多个play
    ansible 批量重启服务
    无法执行 BACKUP LOG,因为当前没有数据库备份
    Microsoft.SqlServer.SmoExtended
    ACTIVEMQ主题、队列设置用户名密码
    Ansible的配置文件:
    MQTT协议之订阅及发布(使用paho-mqtt-client或mqttv3实现)
    采用基于MQTT的ActiveMQ实现消息推送
    ansible Introduction To Ad-Hoc Commands:
  • 原文地址:https://www.cnblogs.com/Manual-Linux/p/11404654.html
Copyright © 2020-2023  润新知