LINUX.ORG.RU

unordered_map и ключ-структура

 


0

4

Ключом для map или unordered_map должна быть такая структура.

struct Coord
{
    Coord()
    {
        this->X=0;
        this->Y=0;
        this->Z=0;
    }
    Coord(long X, long Y, long Z)
    {
        this->X=X;
        this->Y=Y;
        this->Z=Z;
    }
    unsigned int X;
    unsigned int Y;
    unsigned char Z;
};

собственно вопрос, как для нее правильно написать хеш функцию или функцию сравнения (да и собственно, через что будет быстрее - map или unordered_map (тип значения - shared_ptr)


Мне кажется, что map вообще никаких хеш-функций не держит. Какие ограничения на X,Y,Z? Кстати, почему X и Y unsigned int, а Z — unsigned char, при том, что в конструкторе вы инициализируете их от signed long?

elfy
()
Ответ на: комментарий от elfy

Z от 1 до 24
X, Y от 0 до 131071 (в случае z<=18) или до 8388605 (когда Z==24)

Кстати, почему X и Y unsigned int, а Z — unsigned char, при том, что в конструкторе вы инициализируете их от signed long

не успел поправить

Мне кажется, что map вообще никаких хеш-функций не держит

Ну да, для map нужно сравнение (по умолчанию std::less)

Uter
() автор топика

Тс прости, я пароль потерял, а региться ради этого влом:

Кто нибудь, запилите уже реквест в l-o-r по уменьшению шрифта на пару поинтов в code-блоке. С телефона нереально же читать стало!

anonymous
()

Можно по такому принципу:

/* 
 * Dragon book hash function 
 * 
 */ 

int Symbol_table :: hash(char *s) 
{ 
    char* ss = s; 
    unsigned int h = 0, g; 
    for (; *ss != '\0"; ss++) 
    { 
        h = (h << 4) + *ss; 
        if (g = h & 0xf0000000) 
        { 
            h ^= g >> 24; 
            h ^= g; 
        } 
    } 
    return h % table_size; 
} 

quiet_readonly ★★★★
()
Ответ на: комментарий от quiet_readonly

То есть так будет нормально?

template<>
struct hash<Coord>
	: public _Bitwise_hash<Coord>
{	
};

//при том что
template<class _Kty>
	struct _Bitwise_hash
		: public unary_function<_Kty, size_t>
	{	// hash functor for plain old data
	size_t operator()(const _Kty& _Keyval) const
		{	// hash _Keyval to size_t value by pseudorandomizing transform
		return (_Hash_seq((const unsigned char *)&_Keyval, sizeof (_Kty)));
		}
	};

inline size_t _Hash_seq(const unsigned char *_First, size_t _Count)
	{	// FNV-1a hash function for bytes in [_First, _First+_Count)

	const size_t _FNV_offset_basis = 2166136261U;
	const size_t _FNV_prime = 16777619U;


	size_t _Val = _FNV_offset_basis;
	for (size_t _Next = 0; _Next < _Count; ++_Next)
		{	// fold in another byte
		_Val ^= (size_t)_First[_Next];
		_Val *= _FNV_prime;
		}

	return (_Val);
	}
А как быть если X и Y типа double (я так понимаю, одинаковые значения могут иметь разное прдеставление)?

Uter
() автор топика
template<
    class Key,
    class T,
    class Hash = std::hash<Key>,
    class KeyEqual = std::equal_to<Key>,
    class Allocator = std::allocator< std::pair<const Key, T> >
> class unordered_map;

так шо нужен не только Hash, но и KeyEqual!

Вот тут есть пример того, как сделать хеш для своей структуры.

AF ★★★
()
Ответ на: комментарий от Uter

А с Hash в чем проблема? Пример есть! Выбирай функцию для своих ключей и вперед.

ЗЫ: а упорядочить структуры в массиве по координатам не хочешь?

AF ★★★
()
Последнее исправление: AF (всего исправлений: 1)

ерез что будет быстрее - map или unordered_map

В общем случае unordered_map быстрее, чем map.

andreyu ★★★★★
()
Ответ на: комментарий от Uter

Я тут еще чего подумал, с ограничениями

Z от 1 до 24
X, Y от 0 до 131071 (в случае z<=18) или до 8388605 (когда Z==24)

На Z отвести 8 бит

На X, Y по 20

Итого X, Y, Z можно засунуть в одну переменную типа long long. А для long long уже есть спецификация у std::hash

AF ★★★
()
Последнее исправление: AF (всего исправлений: 1)
Ответ на: комментарий от AF

А для long long уже есть спецификация у std::hash

Гм, ну так это все тот же _Bitwise_hash (по крайней мере в STL от MS)

Uter
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.