C 大整数的小查找表
我想制作一个快速、相对较小的查找表,但输入范围较大: -输入:最大32位值(32位颜色值) -输出:最大8位索引(表索引) 类似下面的代码。(如果索引的值超过256个,则索引仅为0) 不管我怎么想,我总是以这样的事情结束。对于32位(4294967296个状态)的输入范围,我需要分配太多的内存,才能获得256个可能的输出。我也不希望在C 大整数的小查找表,c,performance,lookup-tables,C,Performance,Lookup Tables,我想制作一个快速、相对较小的查找表,但输入范围较大: -输入:最大32位值(32位颜色值) -输出:最大8位索引(表索引) 类似下面的代码。(如果索引的值超过256个,则索引仅为0) 不管我怎么想,我总是以这样的事情结束。对于32位(4294967296个状态)的输入范围,我需要分配太多的内存,才能获得256个可能的输出。我也不希望在for循环内部形成256个if else 有没有一种快速的方法,不管是表还是非表,最终都有相同的功能,我还没有听说过 非常感谢 您可以使用哈希表将32位值映射到查找
for
循环内部形成256个if else
有没有一种快速的方法,不管是表还是非表,最终都有相同的功能,我还没有听说过
非常感谢 您可以使用哈希表将32位值映射到查找表索引。哈希表的长度应明显长于查找表,以减少哈希冲突的可能性 下面的示例使用哈希表的线性搜索,从从输入值派生的哈希值开始搜索,直到找到匹配项或找到空哈希表。如果找不到输入值,并且查找表和哈希表中都有空间(因为它比查找表长,所以应该有空间),则将输入值添加到查找表中,并更新哈希表。它使用的哈希表的大小是查找表的四倍 该示例在每个过程中使用相同的伪随机序列执行两个过程。第一步应该主要填充查找表并更新哈希表。第二个过程不应对查找表或哈希表进行任何更改,因为它只是重复第一个序列
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
struct hash_index {
uint8_t index;
char used;
};
#define HASHBITS 10
#define HASHSIZE (1U << HASHBITS)
#define HASHMASK (HASHSIZE - 1)
#define LOOKUPSIZE 256U
static uint8_t getIndx(uint32_t value);
static uint32_t lookup[LOOKUPSIZE];
static struct hash_index hashtab[HASHSIZE];
static unsigned int count = 0;
static unsigned int tot_collisions = 0;
static unsigned int max_collisions = 0;
static unsigned int hash_used = 0;
int main(void) {
int pass;
unsigned int i;
uint32_t value;
uint8_t index;
unsigned int successes;
unsigned int failures;
int ok;
printf("Lookup size: %u, Hash size: %u\n", LOOKUPSIZE, HASHSIZE);
for (pass = 1; pass <= 2; pass++) {
successes = 0;
failures = 0;
tot_collisions = 0;
max_collisions = 0;
/* Not resetting hash_used because it shouldn't change after first pass. */
printf("\nPass %d, currently used hashes: %u\n\n", pass, hash_used);
srand(1);
for (i = 0; i < 260; i++) {
static const char * const outcomes[2] = {"FAIL", "OK"};
value = rand();
index = getIndx(value);
ok = lookup[index] == value;
printf("%" PRIu32 " -> %" PRIu8 " (%s)\n", value, index, outcomes[ok]);
if (ok) {
successes++;
} else {
failures++;
}
}
printf("\nSuccesses: %u, Failures: %u\n", successes, failures);
printf("Used hashes: %u, Total collisions: %u, Max collisions: %u\n\n",
hash_used, tot_collisions, max_collisions);
}
return 0;
}
static uint8_t getIndx(uint32_t value) {
unsigned int initial_hash;
unsigned int hash;
unsigned int collisions = 0;
uint8_t index;
/*
* Search for value using hash table, starting at position hashed from value.
*
* The hash table is longer than the maximum number of used entries,
* so we should always be able to find an unused entry in the hash table.
*/
initial_hash = ((value * UINT32_C(0x61c88647)) >> (32 - HASHBITS)) & HASHMASK;
for (hash = initial_hash;
collisions < HASHSIZE && hashtab[hash].used;
hash = (hash + 1) & HASHMASK) {
/*
* This hash table entry is used. Get the corresponding index in the
* main lookup table to check if the value matches.
*/
index = hashtab[hash].index;
if (lookup[index] == value) {
/* Matching value found. Return its index in the main table. */
return index;
}
/* Count hash collisions and total hash collisions. */
collisions++;
tot_collisions++;
if (max_collisions < collisions) {
/* Update max hash collisions for diagnostics. */
max_collisions = collisions;
}
}
/* Value not found. */
if (count < LOOKUPSIZE && collisions < HASHSIZE) {
/*
* There is room in the main lookup table for the new value
* and room in the hash table. The index of the new value in the
* main lookup table will be the current count, which will be incremented.
*/
index = count++;
/*
* Add value to main lookup table,
* add index in main lookup table to hash table,
* and return the index in the main lookup table.
*/
lookup[index] = value;
hashtab[hash].index = index;
hashtab[hash].used = 1;
hash_used++; /* Count of used hash table entries for diagnostics. */
return index;
}
/*
* Value not found and main lookup table is full or hash table is full.
* Give up.
*/
return 0;
}
#包括
#包括
#包括
#包括
#包括
结构散列索引{
uint8_t指数;
使用的煤焦;
};
#定义散列位10
#定义HASHSIZE(1U听起来像是你在寻找“哈希表”。你有没有研究过这是否符合你的需要?哈希表有多种变体,取决于什么样的内存和性能折衷点适合你的需要。谷歌搜索“c字典”可以帮你。请注意if(count>255)
永远不会是真的,因为count
属于uint8\u t
类型。表中元素的最大数量为256是正确的吗?您的目标是哪种硬件?您想要什么?一个不使用太多内存的解决方案?您想要一个能够记住前256个输入并返回其输入的函数当它再次看到这些输入时分配数字,其他输入为零?仅供参考,您为size
元素分配空间,但初始化size+1
元素。这看起来很有希望。您从哪里学到了散列?您能推荐一本书、一个网站或其他什么吗?因为我对它一无所知。。。
0
1
2
0
1
2
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
struct hash_index {
uint8_t index;
char used;
};
#define HASHBITS 10
#define HASHSIZE (1U << HASHBITS)
#define HASHMASK (HASHSIZE - 1)
#define LOOKUPSIZE 256U
static uint8_t getIndx(uint32_t value);
static uint32_t lookup[LOOKUPSIZE];
static struct hash_index hashtab[HASHSIZE];
static unsigned int count = 0;
static unsigned int tot_collisions = 0;
static unsigned int max_collisions = 0;
static unsigned int hash_used = 0;
int main(void) {
int pass;
unsigned int i;
uint32_t value;
uint8_t index;
unsigned int successes;
unsigned int failures;
int ok;
printf("Lookup size: %u, Hash size: %u\n", LOOKUPSIZE, HASHSIZE);
for (pass = 1; pass <= 2; pass++) {
successes = 0;
failures = 0;
tot_collisions = 0;
max_collisions = 0;
/* Not resetting hash_used because it shouldn't change after first pass. */
printf("\nPass %d, currently used hashes: %u\n\n", pass, hash_used);
srand(1);
for (i = 0; i < 260; i++) {
static const char * const outcomes[2] = {"FAIL", "OK"};
value = rand();
index = getIndx(value);
ok = lookup[index] == value;
printf("%" PRIu32 " -> %" PRIu8 " (%s)\n", value, index, outcomes[ok]);
if (ok) {
successes++;
} else {
failures++;
}
}
printf("\nSuccesses: %u, Failures: %u\n", successes, failures);
printf("Used hashes: %u, Total collisions: %u, Max collisions: %u\n\n",
hash_used, tot_collisions, max_collisions);
}
return 0;
}
static uint8_t getIndx(uint32_t value) {
unsigned int initial_hash;
unsigned int hash;
unsigned int collisions = 0;
uint8_t index;
/*
* Search for value using hash table, starting at position hashed from value.
*
* The hash table is longer than the maximum number of used entries,
* so we should always be able to find an unused entry in the hash table.
*/
initial_hash = ((value * UINT32_C(0x61c88647)) >> (32 - HASHBITS)) & HASHMASK;
for (hash = initial_hash;
collisions < HASHSIZE && hashtab[hash].used;
hash = (hash + 1) & HASHMASK) {
/*
* This hash table entry is used. Get the corresponding index in the
* main lookup table to check if the value matches.
*/
index = hashtab[hash].index;
if (lookup[index] == value) {
/* Matching value found. Return its index in the main table. */
return index;
}
/* Count hash collisions and total hash collisions. */
collisions++;
tot_collisions++;
if (max_collisions < collisions) {
/* Update max hash collisions for diagnostics. */
max_collisions = collisions;
}
}
/* Value not found. */
if (count < LOOKUPSIZE && collisions < HASHSIZE) {
/*
* There is room in the main lookup table for the new value
* and room in the hash table. The index of the new value in the
* main lookup table will be the current count, which will be incremented.
*/
index = count++;
/*
* Add value to main lookup table,
* add index in main lookup table to hash table,
* and return the index in the main lookup table.
*/
lookup[index] = value;
hashtab[hash].index = index;
hashtab[hash].used = 1;
hash_used++; /* Count of used hash table entries for diagnostics. */
return index;
}
/*
* Value not found and main lookup table is full or hash table is full.
* Give up.
*/
return 0;
}