C++ 哈希搜索函数卡在无休止的 "else" 和 "while" 循环中
C++ Hashing search function stuck in endless "else" and "while" loop
如果哈希表数组中不存在要查找的生成的随机数,则程序将陷入函数void hashSearch()
的死循环,
而它应该跳出循环并输出未找到搜索项。代码中的确切位置是这些输出的位置:
cout << "stuck in else loop \n";
和 cout << "stuck in while loop end \n";
.
我用谷歌搜索了一下,但找不到类似的例子。
#include <iostream>
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
#include <chrono>
using namespace std;
int arr [1000];
int arr2 [1000];
int randArrayInt, n, randSearchItem, searchInt, address, size2;
void printZeroArr();
void linearSentinelSearch();
void printHashArray();
void hashSearch();
int main ()
{
srand (time(nullptr)); //initialize random seed:
n = rand() % 900 + 100; //random integer number from 100 - 1000, length of the array
//n = rand() % 10; // random number in the range 1-10 for sanity tests, length of the array
//randSearchItem = rand() % 10 + 1;
randSearchItem = rand() % 900 + 100; //this is the number to search for
cout << "Array length is " << n << endl;
cout << "[";
for (int i = 0; i <= n; i++)
{
randArrayInt = rand() % 900 + 100;
//randArrayInt = rand() % 10 + 1; // generate random 1-10 number for for sanity tests
arr[i] = randArrayInt; // insert into array position the generated random number
cout<< " " << arr[i]; // print out array element at current loop position
}
cout << " ]\n" << endl;
printZeroArr();
}
void printZeroArr()
{
size2 = n + 1; //length of hashed array
cout << "This is the random key to search for in array: " << randSearchItem << endl;
cout << "This is the size2 length " << size2 << endl;
cout << "This is the hasharray with zeros" << endl;
cout << "[";
for (int i = 0; i <= size2; i++)
{
arr2[i] = 0; // insert into hasharray number 0
cout<< " " << arr2[i]; // print out hasharray element at current loop position
}
cout << " ]\n" << endl;
linearSentinelSearch();
}
void linearSentinelSearch()
{
auto start = std::chrono::high_resolution_clock::now();
arr[n + 1] = randSearchItem;
//cout << "testing arr[n + 1] is " << arr[n + 1] << endl;
int i = 0;
while (arr[i] != randSearchItem) i++;
if (i == n + 1)
cout << "Sentinel search did not found the searchitem in random array" << "\n" << endl;
else
cout << "Searchitem found in array with linearsearch at position " << i << "\n" << endl;
auto finish = std::chrono::high_resolution_clock::now();
chrono::duration<double> elapsed = finish - start;
cout << "Elapsed time: " << elapsed.count() << " s\n";
printHashArray();
}
void printHashArray()
{
//cout << "printing out 'address' value, or the modulo result: " << endl;
//cout << "[";
for (int i = 0; i <= n; i++)
{
address = arr[i] % size2;
//cout << " " << address;
while (arr2[address] != 0)
{
if (address == size2 - 1)
{
address = 0;
} else
{
address++;
}
}
arr2[address] = arr[i];
}
//cout << " ]\n" << endl;
cout << "This is the hasharray with hashitems" << endl;
cout << "[";
for (int i = 0; i <= size2; i++)
{
cout << " " << arr2[i];
}
cout << " ]\n" << endl; hashSearch();
}
void hashSearch()
{
auto start = std::chrono::high_resolution_clock::now();
int searchInt = randSearchItem % size2;
while ((arr2[searchInt] != 0) && (arr2[searchInt] != randSearchItem))
{
if (searchInt == size2 - 1)
{
searchInt = 0;
cout << "if loop \n";
}
else
{
searchInt++;
cout << " stuck in else loop \n";
}
cout << " stuck in while loop end \n";
}
if (searchInt == 0) {
cout << "Search item not found using hashSearch" << endl;
} else {
cout << "Search item " << randSearchItem << " found using hashSearch at position " << searchInt << " in arr2." << endl;
}
auto finish = std::chrono::high_resolution_clock::now();
chrono::duration<double> elapsed = finish - start;
cout << "Elapsed time: " << elapsed.count() << " s\n";
}
而它应该跳出循环并输出未找到搜索项。
搜索 cout << " stuck in else loop \n";
和 cout << " stuck in while loop end \n";
.
您想在到达数组末尾时停止循环:为此,您将要搜索的项目设置为零:
if (searchInt == size2 - 1)
{
searchInt = 0;
cout << "if loop \n";
}
但是在循环控制中,你不测试那个。您只测试当前索引处的数组元素是否为零(未找到)或要搜索的项目(已找到):
while ((arr2[searchInt] != 0) && (arr2[searchInt] != randSearchItem)) ...
您需要进行额外的测试:
while ((searchInt != 0) && ...) ...
我花了一段时间才知道您想编写一个开放地址 hastable,其中零标记未使用的插槽。哈希值只是数字本身。使用零作为空槽的指示符并不理想:您不能存储散列码模 table 大小为零的数字。
我还会用非空函数对此进行编码,其中 return 值是索引或一些明确的值,意思是 "not found",也许是 -1。 (或者,您可以 return 一个指向已找到项目的指针,或者 NULL
如果未找到该项目——毕竟,散列数组中的索引是散列 table 的一部分的内部结构,与调用者无关。)
那你可以早点用returns:
int hashSearch(const int *arr2, int size2, int item)
{
int i = item % size2;
for (; i < size2; i++) {
if (arr2[i] == -1) break; // -1 indicated unused space
if (arr2[i] == item) return i; // return index of item
}
return -1; // not found!
}
但是当你的散列码接近数组大小时,如果没有空间容纳更多元素,你会怎么做?您将需要在末尾添加额外的 space ,否则您将需要环绕。也许这就是您想通过将索引设置回零来实现的。在您的情况下,数组已满,因此没有可作为循环中断标准的零。你将不得不找到另一个标准。您可以通过使散列 table 比条目数大 30% 左右来确保有零。或者您可以尝试检测索引是否已经绕过原始索引。
正如在评论中已经向您指出的那样:尝试使用函数参数和局部变量,而不是将所有内容都放入全局 space。此外,函数调用的链接,函数中的最后一件事是调用下一个函数,这很奇怪。将所有顺序调用放入 main 可能更好。
如果哈希表数组中不存在要查找的生成的随机数,则程序将陷入函数void hashSearch()
的死循环,
而它应该跳出循环并输出未找到搜索项。代码中的确切位置是这些输出的位置:
cout << "stuck in else loop \n";
和 cout << "stuck in while loop end \n";
.
我用谷歌搜索了一下,但找不到类似的例子。
#include <iostream>
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
#include <chrono>
using namespace std;
int arr [1000];
int arr2 [1000];
int randArrayInt, n, randSearchItem, searchInt, address, size2;
void printZeroArr();
void linearSentinelSearch();
void printHashArray();
void hashSearch();
int main ()
{
srand (time(nullptr)); //initialize random seed:
n = rand() % 900 + 100; //random integer number from 100 - 1000, length of the array
//n = rand() % 10; // random number in the range 1-10 for sanity tests, length of the array
//randSearchItem = rand() % 10 + 1;
randSearchItem = rand() % 900 + 100; //this is the number to search for
cout << "Array length is " << n << endl;
cout << "[";
for (int i = 0; i <= n; i++)
{
randArrayInt = rand() % 900 + 100;
//randArrayInt = rand() % 10 + 1; // generate random 1-10 number for for sanity tests
arr[i] = randArrayInt; // insert into array position the generated random number
cout<< " " << arr[i]; // print out array element at current loop position
}
cout << " ]\n" << endl;
printZeroArr();
}
void printZeroArr()
{
size2 = n + 1; //length of hashed array
cout << "This is the random key to search for in array: " << randSearchItem << endl;
cout << "This is the size2 length " << size2 << endl;
cout << "This is the hasharray with zeros" << endl;
cout << "[";
for (int i = 0; i <= size2; i++)
{
arr2[i] = 0; // insert into hasharray number 0
cout<< " " << arr2[i]; // print out hasharray element at current loop position
}
cout << " ]\n" << endl;
linearSentinelSearch();
}
void linearSentinelSearch()
{
auto start = std::chrono::high_resolution_clock::now();
arr[n + 1] = randSearchItem;
//cout << "testing arr[n + 1] is " << arr[n + 1] << endl;
int i = 0;
while (arr[i] != randSearchItem) i++;
if (i == n + 1)
cout << "Sentinel search did not found the searchitem in random array" << "\n" << endl;
else
cout << "Searchitem found in array with linearsearch at position " << i << "\n" << endl;
auto finish = std::chrono::high_resolution_clock::now();
chrono::duration<double> elapsed = finish - start;
cout << "Elapsed time: " << elapsed.count() << " s\n";
printHashArray();
}
void printHashArray()
{
//cout << "printing out 'address' value, or the modulo result: " << endl;
//cout << "[";
for (int i = 0; i <= n; i++)
{
address = arr[i] % size2;
//cout << " " << address;
while (arr2[address] != 0)
{
if (address == size2 - 1)
{
address = 0;
} else
{
address++;
}
}
arr2[address] = arr[i];
}
//cout << " ]\n" << endl;
cout << "This is the hasharray with hashitems" << endl;
cout << "[";
for (int i = 0; i <= size2; i++)
{
cout << " " << arr2[i];
}
cout << " ]\n" << endl; hashSearch();
}
void hashSearch()
{
auto start = std::chrono::high_resolution_clock::now();
int searchInt = randSearchItem % size2;
while ((arr2[searchInt] != 0) && (arr2[searchInt] != randSearchItem))
{
if (searchInt == size2 - 1)
{
searchInt = 0;
cout << "if loop \n";
}
else
{
searchInt++;
cout << " stuck in else loop \n";
}
cout << " stuck in while loop end \n";
}
if (searchInt == 0) {
cout << "Search item not found using hashSearch" << endl;
} else {
cout << "Search item " << randSearchItem << " found using hashSearch at position " << searchInt << " in arr2." << endl;
}
auto finish = std::chrono::high_resolution_clock::now();
chrono::duration<double> elapsed = finish - start;
cout << "Elapsed time: " << elapsed.count() << " s\n";
}
而它应该跳出循环并输出未找到搜索项。
搜索 cout << " stuck in else loop \n";
和 cout << " stuck in while loop end \n";
.
您想在到达数组末尾时停止循环:为此,您将要搜索的项目设置为零:
if (searchInt == size2 - 1)
{
searchInt = 0;
cout << "if loop \n";
}
但是在循环控制中,你不测试那个。您只测试当前索引处的数组元素是否为零(未找到)或要搜索的项目(已找到):
while ((arr2[searchInt] != 0) && (arr2[searchInt] != randSearchItem)) ...
您需要进行额外的测试:
while ((searchInt != 0) && ...) ...
我花了一段时间才知道您想编写一个开放地址 hastable,其中零标记未使用的插槽。哈希值只是数字本身。使用零作为空槽的指示符并不理想:您不能存储散列码模 table 大小为零的数字。
我还会用非空函数对此进行编码,其中 return 值是索引或一些明确的值,意思是 "not found",也许是 -1。 (或者,您可以 return 一个指向已找到项目的指针,或者 NULL
如果未找到该项目——毕竟,散列数组中的索引是散列 table 的一部分的内部结构,与调用者无关。)
那你可以早点用returns:
int hashSearch(const int *arr2, int size2, int item)
{
int i = item % size2;
for (; i < size2; i++) {
if (arr2[i] == -1) break; // -1 indicated unused space
if (arr2[i] == item) return i; // return index of item
}
return -1; // not found!
}
但是当你的散列码接近数组大小时,如果没有空间容纳更多元素,你会怎么做?您将需要在末尾添加额外的 space ,否则您将需要环绕。也许这就是您想通过将索引设置回零来实现的。在您的情况下,数组已满,因此没有可作为循环中断标准的零。你将不得不找到另一个标准。您可以通过使散列 table 比条目数大 30% 左右来确保有零。或者您可以尝试检测索引是否已经绕过原始索引。
正如在评论中已经向您指出的那样:尝试使用函数参数和局部变量,而不是将所有内容都放入全局 space。此外,函数调用的链接,函数中的最后一件事是调用下一个函数,这很奇怪。将所有顺序调用放入 main 可能更好。