散列查找:
根据散列函数确定关键词key的存储位置,将key存储在一张hash哈希表内,然后根据一定的规则(线性探测,平方探测,分离链接等)来规避相同key的数据之间的冲突。

如上图,散列表的性能和装填因子阿法有关,一般来说阿法不要超过0.85,并且一般来说,表长取大于且最接近元素数量的质数。

解决冲突时,如下图所示,查找和插入时,遇到相同的K,根据当前的冲突处理规则后移数据的摆放位置。

以下是散列表C语言模板函数:

#define MAXTABLESIZE 100000 /* 允许开辟的最大散列表长度 */
typedef int ElementType;    /* 关键词类型用整型 */
typedef int Index;          /* 散列地址类型 */
typedef Index Position;     /* 数据所在位置与散列地址是同一类型 */
/* 散列单元状态类型,分别对应:有合法元素、空单元、有已删除元素 */
typedef enum { Legitimate, Empty, Deleted } EntryType;typedef struct HashEntry Cell; /* 散列表单元类型 */
struct HashEntry{ElementType Data; /* 存放元素 */EntryType Info;   /* 单元状态 */
};typedef struct TblNode *HashTable; /* 散列表类型 */
struct TblNode {   /* 散列表结点定义 */int TableSize; /* 表的最大长度 */Cell *Cells;   /* 存放散列单元数据的数组 */
};int NextPrime( int N )
{ /* 返回大于N且不超过MAXTABLESIZE的最小素数 */int i, 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; /* for正常结束,说明p是素数 */else  p += 2; /* 否则试探下一个奇数 */}return p;
}HashTable CreateTable( int TableSize )
{HashTable H;int i;H = (HashTable)malloc(sizeof(struct TblNode));/* 保证散列表最大长度是素数 */H->TableSize = NextPrime(TableSize);/* 声明单元数组 */H->Cells = (Cell *)malloc(H->TableSize*sizeof(Cell));/* 初始化单元状态为“空单元” */for( i=0; i<H->TableSize; i++ )H->Cells[i].Info = Empty;return H;
}
Position Find( HashTable H, ElementType Key )
{Position CurrentPos, NewPos;int CNum = 0; /* 记录冲突次数 */NewPos = CurrentPos = Hash( Key, H->TableSize ); /* 初始散列位置 *//* 当该位置的单元非空,并且不是要找的元素时,发生冲突 */while( H->Cells[NewPos].Info!=Empty && H->Cells[NewPos].Data!=Key ) {/* 字符串类型的关键词需要 strcmp 函数!! *//* 统计1次冲突,并判断奇偶次 */if( ++CNum%2 ){ /* 奇数次冲突 */NewPos = CurrentPos + (CNum+1)*(CNum+1)/4; /* 增量为+[(CNum+1)/2]^2 */if ( NewPos >= H->TableSize )NewPos = NewPos % H->TableSize; /* 调整为合法地址 */}else { /* 偶数次冲突 */NewPos = CurrentPos - CNum*CNum/4; /* 增量为-(CNum/2)^2 */while( NewPos < 0 )NewPos += H->TableSize; /* 调整为合法地址 */}}return NewPos; /* 此时NewPos或者是Key的位置,或者是一个空单元的位置(表示找不到)*/
}bool Insert( HashTable H, ElementType Key )
{Position Pos = Find( H, Key ); /* 先检查Key是否已经存在 */if( H->Cells[Pos].Info != Legitimate ) { /* 如果这个单元没有被占,说明Key可以插入在此 */H->Cells[Pos].Info = Legitimate;H->Cells[Pos].Data = Key;/*字符串类型的关键词需要 strcpy 函数!! */return true;}else {printf("键值已存在");return false;}
}
#define KEYLENGTH 15                   /* 关键词字符串的最大长度 */
typedef char ElementType[KEYLENGTH+1]; /* 关键词类型用字符串 */
typedef int Index;                     /* 散列地址类型 */
/******** 以下是单链表的定义 ********/
typedef struct LNode *PtrToLNode;
struct LNode {ElementType Data;PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;
/******** 以上是单链表的定义 ********/typedef struct TblNode *HashTable; /* 散列表类型 */
struct TblNode {   /* 散列表结点定义 */int TableSize; /* 表的最大长度 */List Heads;    /* 指向链表头结点的数组 */
};HashTable CreateTable( int TableSize )
{HashTable H;int i;H = (HashTable)malloc(sizeof(struct TblNode));/* 保证散列表最大长度是素数,具体见代码5.3 */H->TableSize = NextPrime(TableSize);/* 以下分配链表头结点数组 */H->Heads = (List)malloc(H->TableSize*sizeof(struct LNode));/* 初始化表头结点 */for( i=0; i<H->TableSize; i++ ) {H->Heads[i].Data[0] = '\0';H->Heads[i].Next = NULL;}return H;
}Position Find( HashTable H, ElementType Key )
{Position P;Index Pos;Pos = Hash( Key, H->TableSize ); /* 初始散列位置 */P = H->Heads[Pos].Next; /* 从该链表的第1个结点开始 *//* 当未到表尾,并且Key未找到时 */ while( P && strcmp(P->Data, Key) )P = P->Next;return P; /* 此时P或者指向找到的结点,或者为NULL */
}bool Insert( HashTable H, ElementType Key )
{Position P, NewCell;Index Pos;P = Find( H, Key );if ( !P ) { /* 关键词未找到,可以插入 */NewCell = (Position)malloc(sizeof(struct LNode));strcpy(NewCell->Data, Key);Pos = Hash( Key, H->TableSize ); /* 初始散列位置 *//* 将NewCell插入为H->Heads[Pos]链表的第1个结点 */NewCell->Next = H->Heads[Pos].Next;H->Heads[Pos].Next = NewCell; return true;}else { /* 关键词已存在 */printf("键值已存在");return false;}
}void DestroyTable( HashTable H )
{int i;Position P, Tmp;/* 释放每个链表的结点 */for( i=0; i<H->TableSize; i++ ) {P = H->Heads[i].Next;while( P ) {Tmp = P->Next;free( P );P = Tmp;}}free( H->Heads ); /* 释放头结点数组 */free( H );        /* 释放散列表结点 */
}

例题一:11-散列1 电话聊天狂人 (25分)
给定大量手机用户通话记录,找出其中通话次数最多的聊天狂人。
输入格式:
输入首先给出正整数N(≤10e​5​​ ),为通话记录条数。随后N行,每行给出一条通话记录。简单起见,这里只列出拨出方和接收方的11位数字构成的手机号码,其中以空格分隔。

输出格式:
在一行中给出聊天狂人的手机号码及其通话次数,其间以空格分隔。如果这样的人不唯一,则输出狂人中最小的号码及其通话次数,并且附加给出并列狂人的人数。

输入样例:
4
13005711862 13588625832
13505711862 13088625832
13588625832 18087925832
15005713862 13588625832

输出样例:
13588625832 3

输入样例2:
4
13005711862 13588625832
13005711862 13588625832
13005711861 13588625838
13005711861 13588625838
输出样例2:
13005711861 2 4

解法一:
读入所有数据存在数组内,用STL的sort()快速排序,然后如果有相同的元素出现,则将当前次数+1。再设置一个变量记录最大次数。考虑到很可能有多个最大次数的ID,题目中还要求补充输出最大次数的人数。所以,需要用一个vector来记录,最后用vector的size来代表人数。

优点:编程简单快捷(适合考试做)
缺点:无法拓展解决动态插入的问题,且效率不高

/*散列1 电话聊天狂人*/
#include <iostream>
#include <stdio.h>
#include <string>
#include <algorithm>
#include <vector>using namespace std;const int MaxNumber = 10e5;
string List[MaxNumber];
vector<int> vec;int main()
{   int MaxTimes=0, NowTimes=1;int FinalUserID;int N;cin >> N;for (int i = 0; i < N*2; i++)cin >> List[i];sort(List, List+N*2);for (int i = 0; i < N * 2; i++){if (i == 0) continue;if (List[i] == List[i - 1]) {NowTimes++;if (i == N * 2 - 1){if (MaxTimes == NowTimes)vec.push_back(N * 2 - 1);}}else{  if (MaxTimes < NowTimes){if(MaxTimes != 0) vec.clear();//清空老容器MaxTimes = NowTimes;FinalUserID = i - 1;vec.push_back(FinalUserID);//推入最新的容器}else if (MaxTimes == NowTimes)vec.push_back(i - 1);NowTimes = 1;//重新初始化}}if(vec.size() == 1)cout << List[vec[0]] << " " << MaxTimes ;elsecout << List[vec[0]] << " " << MaxTimes << " " << vec.size();return 0;
}

提交结果如下:

解法二:
用带链表的散列表(分离链接法)来做
思路:
按部就班地先创建好空表,写好hash散列函数,然后一个个将数据插入散列表的每个格子中的单项链表中。最后写一个判断和输出程序,找出最狂的人,和狂人的数量。

需要注意的是:
1.如H->Heads[i].Data[0],这里Data是个sring,所以Data[0] = '\0’初始化相当于Data = “”,都是将字符串置空,但要注意单双引号
2.strcp,strcmp这种是C的写法,在C++中直接进行字符串= > <大于小于等于号的比较或复制就可以了。
3.关于new。 new是一个数组的时候直接 new 数组名[数组大小]就可以了,但注意这种是返回一个指针,等号左边要用一个等号接住。基本类似于malloc的 (指针名)malloc(数组大小 * sizeof(结构体))。

/*散列1 电话聊天狂人*/
#include <iostream>
#include <stdio.h>
#include <string>
#include <algorithm>
#include <vector>
#include <math.h>
using namespace std;const int MaxNumber = 10e5;const int KEYLENGTH = 11;/*关键词字符串的最大长度*/
/*定义单链*/
struct LNode
{string Data;LNode* Next;int count;
};
typedef LNode* List;
typedef LNode* Position;/*定义散列表*/
struct TableNode
{int TableSize;List Heads;
};
typedef TableNode* HashTable;/*找到合适的素数*/
const int MAXTABLESIZE = 1000000;
int NextPrime(int N)
{int i, p = (N % 2) ? N + 2 : N + 1;//从大于N的下一个奇数开始while (p <= MAXTABLESIZE){for (i = (int)sqrt(p); i > 2; i--)if (!(p% i)) break;//能整除i,说明p不是素数if (i == 2) break;//for正常结束,说明p是素数else p += 2;//否则试探下一个奇数}return p;
}int Hash(int key, int p)//除留余数法的hash散列函数
{return key % p;
}HashTable CreateTable(int TableSize)//建哈希表(分离链接法)
{HashTable H;int i;H = new TableNode;H->TableSize = NextPrime(TableSize);H->Heads =new LNode[H->TableSize];for (i = 0; i < H->TableSize; i++)//初始化TableSize个节点{H->Heads[i].Data[0] = '\0';   /*Data是个string,data[0]置空,则str置空*/H->Heads[i].Next = NULL;H->Heads[i].count = 0;}return H;
}void ScanAndOutput(HashTable H)
{int i;int MaxCnt = 0;int PCnt = 0;string MinPhone;List Ptr;MinPhone = "";//初始化str为空,还可以这样写: str[0]='\0';for (i = 0; i < H->TableSize; i++)//扫描链表{Ptr = H->Heads[i].Next;while (Ptr) {if (Ptr->count > MaxCnt)//如果出现更狂的人{MaxCnt = Ptr->count;MinPhone = Ptr->Data;PCnt = 1;//个人计数归1}else if (Ptr->count == MaxCnt){PCnt++;//狂人计数if (MinPhone > Ptr->Data)MinPhone = Ptr->Data;//更新狂人的最小手机号}Ptr = Ptr->Next;}}cout << MinPhone << " " << MaxCnt;if (PCnt > 1)cout << " " << PCnt<<"\n";
}const int  MAXD =  5;/*参与散列映射计算的字符个数,取后5位*/Position Find(HashTable H, string key)
{Position P;//链表中的位置int pos;//哈希表的位置控制//初始化散列位置pos = Hash(stoi(key.substr(KEYLENGTH - MAXD)),H->TableSize); //用stoi将str类型转换为int/*如果用atoi的C语言风格函数,将会带来string 和 const char*的互相转换问题,用stoi比较简单*/P = H->Heads[pos].Next;//从该链表的第一个节点开始/*当未到表尾,并且key未找到,一直链表后方找*/while (P && P->Data != key)P = P->Next;return P;
}bool Insert(HashTable H, string key)
{Position P, NewCell;int pos;P = Find(H, key);if (!P)//关键词未找到,可以插入{NewCell = new LNode;NewCell->Data = key;NewCell->count = 1;pos = Hash(stoi(key.substr(KEYLENGTH - MAXD)),H->TableSize);/*将NewCell插入为H->Heads[pos]链表的第一个节点*/NewCell->Next = H->Heads[pos].Next;//其实就是给了个空值 !!!!!理解错误 换成NULL报错H->Heads[pos].Next = NewCell;return true;}else {  //关键词已存在P->count++;return false;}
}int main()
{int N, i;string Key;HashTable H;cin >> N;H = CreateTable(N * 2);for (i = 0; i < N; i++){cin >> Key;Insert(H, Key);cin >> Key;Insert(H, Key);}ScanAndOutput(H);return 0;
}

效率截图:相比方法一有显著提高

例题二:
11-散列2 Hashing (25分)
The task of this problem is simple: insert a sequence of distinct positive integers into a hash table, and output the positions of the input numbers. The hash function is defined to be H(key)=key%TSize where TSize is the maximum size of the hash table. Quadratic probing (with positive increments only) is used to solve the collisions.

Note that the table size is better to be prime. If the maximum size given by the user is not prime, you must re-define the table size to be the smallest prime number which is larger than the size given by the user.
Input Specification:
Each input file contains one test case. For each case, the first line contains two positive numbers: MSize (≤10e​4​​ ) and N (≤MSize) which are the user-defined table size and the number of input numbers, respectively. Then N distinct positive integers are given in the next line. All the numbers in a line are separated by a space.

Output Specification:
For each test case, print the corresponding positions (index starts from 0) of the input numbers in one line. All the numbers in a line are separated by a space, and there must be no extra space at the end of the line. In case it is impossible to insert the number, print “-” instead.

Sample Input:
4 4
10 6 4 15

Sample Output:
0 1 4 -

思路:
1.判断用户指定的TableSize是不是素数,如果不是就生成一个大于这个输入的第一个素数。
2.建一个哈希表,在插入的同时判断是否成功插入。(如果直到 x+i*i 都还没有找到合适位置,就不用再探了)
3.根据返回的位置值输出。

需要注意的是:
1.一个理解问题!!! 平方探测的套路不是在前一次探测后偏移的位置再往后偏 II个位置。而是从原始位置开始算偏移。举个例子:一开始是在2这个位置,第一次偏移1个,到3如果发现还有冲突发生,就跑到2的后4个,也就是6这个位置。在函数上就直接Hash(x + ii,H)即可,i是循环变量。
2.如果考试时要整简化的,就直接搞个全局Hash数组就完事。

/* 散列二 Hashing */
#include <iostream>
#include <stdio.h>
#include <string>
#include <algorithm>
#include <vector>
#include <math.h>
using namespace std;const int MaxMSize = 10e4;int Hash(int key, int TableSize)
{return key%TableSize; //除留余数法哈希函数
}struct HashNode {int Data;//存放的数据int Info;//单元状态
};struct TableNode {int TableSize;//哈希表大小HashNode* Cells;//哈希表本体
};
typedef TableNode* HashTable;/*找合适的素数TableSize*/
bool IsPrime(int number)
{for (int i = 2; i < number; i++){if (number % i == 0)return false;}return true;
}//找到下一个素数
const int MAXTABLESIZE = 1000000;
int NextPrime(int N)
{   if (N == 1) return 2;int i, p = (N % 2) ? N + 2 : N + 1;//从大于N的下一个奇数开始while (p <= MAXTABLESIZE){for (i = (int)sqrt(p); i > 2; i--)if (!(p% i)) break;//能整除i,说明p不是素数if (i == 2) break;//for正常结束,说明p是素数else p += 2;//否则试探下一个奇数}return p;
}int FindTableSize(int N)
{int TableSize;if (N == 1) return 2;if (IsPrime(N))TableSize = N;elseTableSize = NextPrime(N);return TableSize;
}
/*找TableSize结束*/HashTable CreateTable(int TableSize)
{HashTable H;int i;H = new TableNode;//申请散列表空间H->TableSize = TableSize;H->Cells = new HashNode[TableSize];//申请大小为Tablesize的哈希数组空间for (i = 0; i < H->TableSize; i++)H->Cells[i].Info = 0;//状态全部标记为没有元素,没有插入过,0return H;
}int Insert(HashTable H, int x)
{int pos = Hash(x, H->TableSize);if (H->Cells[pos].Info == 0)//如果此处是空的{H->Cells[pos].Info = 1;H->Cells[pos].Data = x;}else{int i;for (i = 1; i <= H->TableSize / 2; i++)/* 探测到size/2就不用再探测了:因为这个范围足以探测到所有的哈希值了 */{pos = Hash(x + i*i, H->TableSize);/* 这里我最开始写的是pos+i*i,所以一直过不了... */if (H->Cells[pos].Info == 0)//新的位置没有元素{H->Cells[pos].Info = 1;H->Cells[pos].Data = x;break;}}if (i > H->TableSize / 2)//没在1/2Size内找到,说明不可能插入了pos = -1;//用不可能值-1去覆盖上面的pos}return pos;
}int main()
{int MSize, N,TableSize;int Key;//输入的数据cin >> MSize>> N;if (MSize == 0){cout << "-";return 0;}TableSize = FindTableSize(MSize);HashTable H;H = CreateTable(TableSize);for (int i = 0; i < N; i++){int Position;cin >> Key;Position = Insert(H, Key);if (Position != -1)cout << Position;elsecout << "-";if (i != N - 1)//每个输出中间加空格cout << " ";}return 0;
}

例题三:11-散列3 QQ帐户的申请与登陆 (25分)
实现QQ新帐户申请和老帐户登陆的简化版功能。最大挑战是:据说现在的QQ号码已经有10位数了。

输入格式:
输入首先给出一个正整数N(≤10e​5),随后给出N行指令。每行指令的格式为:“命令符(空格)QQ号码(空格)密码”。其中命令符为“N”(代表New)时表示要新申请一个QQ号,后面是新帐户的号码和密码;命令符为“L”(代表Login)时表示是老帐户登陆,后面是登陆信息。QQ号码为一个不超过10位、但大于1000(据说QQ老总的号码是1001)的整数。密码为不小于6位、不超过16位、且不包含空格的字符串。

输出格式:
针对每条指令,给出相应的信息:
1)若新申请帐户成功,则输出“New: OK”;
2)若新申请的号码已经存在,则输出“ERROR: Exist”;
3)若老帐户登陆成功,则输出“Login: OK”;
4)若老帐户QQ号码不存在,则输出“ERROR: Not Exist”;
5)若老帐户密码错误,则输出“ERROR: Wrong PW”。
输入样例1:
5
L 1234567890 myQQ@qq.com
N 1234567890 myQQ@qq.com
N 1234567890 myQQ@qq.com
L 1234567890 myQQ@qq
L 1234567890 myQQ@qq.com
输出样例1:
ERROR: Not Exist
New: OK
ERROR: Exist
ERROR: Wrong PW
Login: OK
输入样例2:(用来过第三个测试点)
4
N 1234567890 myQQ@qq.com
L 1234567890 myQQ@qq.com
N 1002 112233X
L 1002 112233X

思路:
和上面的题目一样,用分离链接法(链表)的散列表来解决。为了保证时间不超,截取最后七位的QQ号码作为放进哈希函数的原始计算数据。注意要在Find和Insert里面做好小于7位数的判断。

需要注意的事:
1.要注意if(!P),此时P是一个指针。这种写法的出错了好难查出来,这样等于是P= NULL时进循环。还是if(P != NULL)比较不容易粗心出错。
2.复习了stoi()的用法。
3.复习了substr()的用法。substr(str截取的开始位置,str截取的结束位置)。

/* 散列二 Hashing */
#include <iostream>
#include <stdio.h>
#include <string>
#include <algorithm>
#include <vector>
#include <math.h>
using namespace std;const int MaxMSize = 10e5;struct LNode //单项链表节点
{string UserName;string PassWord;LNode* next;
};
typedef LNode* List;
typedef LNode* Position;struct HashTableNode //定义哈希表
{int TableSize;List heads;
};
typedef HashTableNode* HashTable;bool Isprime(int x)
{int i;for (i = 2; i < x; i++){if (x % i == 0)return false;}return true;
}const int MaxTableSize = 1000000;
int nextprime(int N)
{int i, p = (N % 2) ? N + 2 : N + 1;//从大于N的下一个奇数开始while (p <= MaxTableSize){for (i = (int)sqrt(p); i > 2; i--)if (!(p% i)) break;//能整除i,说明p不是素数if (i == 2) break;//for正常结束,说明p是素数else p += 2;//否则试探下一个奇数}return p;
}HashTable CreatHash(int  num)
{HashTable H;H = new HashTableNode;H->TableSize = nextprime(num);H->heads = new LNode[H->TableSize];//申请出表数组的物理空间for (int i = 0; i < H->TableSize; i++)//初始化所有节点{H->heads[i].UserName = "";H->heads[i].PassWord = "";H->heads[i].next = NULL;}return H;
}int Hash(int x, int p)//除留余数法
{return x % p;
}List Find( HashTable H,string username)
{int HashPos;if (username.length() < 7)//当QQ号码为小于7位时HashPos = Hash(stoi(username), H->TableSize);elseHashPos = Hash(stoi(username.substr(username.length() - 7, username.length() )),H->TableSize);Position P;P = H->heads[HashPos].next;//指向这个的头节点while (P && P->UserName != username)P = P->next;return P;
}void Insert(HashTable H, string username , string password)
{Position P = Find( H , username);if (!P)//如果没找到,则插入{List NewNode = new LNode;NewNode->UserName = username;NewNode->PassWord = password;NewNode->next = NULL;int HashPos;if (username.length() < 7)HashPos = Hash(stoi(username), H->TableSize);elseHashPos= Hash(stoi(username.substr(username.length() - 7, username.length())), H->TableSize);NewNode->next = H->heads[HashPos].next;//从表头插入(就不需要循环偏移到表尾了)H->heads[HashPos].next = NewNode;cout << "New: OK";}else//找到相同的账号了,抛出已存在错误cout << "ERROR: Exist";
}int main()
{int Num;string Action;string UserName, PassWord;HashTable H;Position P;cin >> Num;H = CreatHash(Num);for (int i = 0; i < Num; i++){cin >> Action >> UserName >> PassWord;if (Action == "L") //登入情况{ P = Find(H, UserName);if (P)//找到了(写if(P)就报错,why?){if (P->PassWord == PassWord)//密码正确cout << "Login: OK";elsecout << "ERROR: Wrong PW";}else//没找到,账号不存在cout << "ERROR: Not Exist";}if (Action == "N")Insert(H , UserName , PassWord);//存入注册的账号密码if (i != Num - 1)cout << "\n";}return 0;
}

PTA 查找(散列查找)相关推荐

  1. 数据结构与算法 ~ 查找 ~ 散列查找(哈希~线性探查法和二次探查法)

    数据结构与算法 ~ 查找 ~ 散列查找(哈希~线性探查法和二次探查法) /*search-hash*/ #include<math.h> #include<stdio.h> # ...

  2. “查找”学习提纲(二)——树型查找和散列查找

    文章目录 前言 代码模板 二叉排序/查找/搜索树查找 适用 性能 代码模板 折半查找和二叉排序树查找总结 平衡二叉(排序)树/AVL树 构造相应层数的树至少需要的结点数 平衡调整的过程 平衡调整的类型 ...

  3. PTA数据结构题目集 第十一周——散列查找

    目录 11-散列1 电话聊天狂人 (25分) 思路 代码 测试点 11-散列2 Hashing (25分) 思路 代码 测试点 11-散列3 QQ帐户的申请与登陆 (25分) 题目大意 思路 代码 测 ...

  4. 哈希表(散列查找)(c/c++)

    通过哈希表进行查找的特点是:不需要比较关键字,而是通过哈希函数计算出关键字的位置.一般来讲,为了进行高效率的查找,要求哈希函数简单均匀.空间利用率高.关键字之间的冲突少. 关于散列查找的实现需要着重考 ...

  5. 数据结构之查找算法:散列查找

    查找算法:散列查找 思维导图: 散列函数和散列表: 构造散列函数的要求: 构造散列函数的方法: 直接定址法: 除留取余法: 数字分析法: 平方取中法: 折叠法: 解决冲突的方法: 开放定址法: 线性探 ...

  6. 查找算法【哈希表】 - 散列查找及性能分析

    查找算法[哈希表] - 散列查找及性能分析 散列表虽然建立了关键字和存储位置之间的直接映像,但冲突不可避免,在散列表的查找过程中,有的关键字可以通过直接定址1次比较找到,有的关键字可能仍然需要和若干关 ...

  7. 散列查找 散列表(哈希表)

    哈希表的平均查找长度是()的函数. A.哈希表的长度 B.哈希表的装填因子 C.哈希函数 D.表中元素的多少 装填因子 = 关键字个数 / 表长 符号表:是 "名字(Name)–属性(Att ...

  8. 【数据结构----笔记2】查找算法之【哈希查找或散列查找】

    /*__________________________________________________________________________________________________ ...

  9. 数据结构(六)散列查找 —— 编程作业01 :电话聊天狂人

    数据结构系列内容的学习目录→\rightarrow→浙大版数据结构学习系列内容汇总.   题目描述: 给定大量手机用户通话记录,找出其中通话次数最多的聊天狂人.   输入格式: 输入首先给出正整数N( ...

最新文章

  1. 审计风险控制流程的起点_审计理论结构的起点和逻辑起点辨析
  2. css 定位兼容性,CSS基础:定位与浏览器兼容性
  3. 基于XMPP协议的aSmack源码分析
  4. dos中for in后面执行多个命令的方法
  5. Python中get()函数用法【详解】——Python系列学习笔记
  6. python bool值要注意的一些地方
  7. pytorch保存模型pth_pytorch中保存的模型文件.pth深入解析
  8. 以太坊使用puppeth工具
  9. SQLite学习总结(3)——SQLite命令及语法
  10. Android JNI(实现自己的JNI_OnLoad函数)
  11. php 循环获取分类,PHP 循环删除无限分类子节点
  12. vb不能插入png图片_VB6.0载入PNG格式图片
  13. 现代计算机教学的特点有哪些,现代信息技术对孩子教育有哪些帮助
  14. xamarin android 标签,Xamarin.Android使用教程:Android项目结构
  15. 传奇hero引擎版本服务端转换GEE引教程教学篇
  16. tongweb java_home_中间件 东方通tongweb的使用
  17. 机器学习常见算法分类汇总
  18. python抢课_一个用python实现的东方时尚(驾校)抢课程序
  19. SVN :找不到这样的主机
  20. 企业微信的消息如何在个人微信上读取?

热门文章

  1. C#让TextBox控件中的滚动条自动处于最下面
  2. 关键词采集网址工具【持久更新】
  3. Activity生命周期(Activity弹出Dialog会触发Activity生命周期吗)
  4. 【python】对象释放,弱引用weaker.ref
  5. mysql dba 兼职_招聘兼职数据共享与交换平台| - 实现网
  6. bp语音识别matlab,【Matlab学习手记】基于带动量项的BP神经网络语音识别
  7. PCB上10A的电流需要走多宽的线?需要几个过孔?
  8. html经典双飞翼布局
  9. July 1st 《宫》
  10. 亲测好用的油管音乐播放器:Tuner Mac版