Сортровка и хэш

Тема в разделе "WASM.A&O", создана пользователем const, 27 дек 2004.

  1. const

    const New Member

    Публикаций:
    0
    Регистрация:
    8 апр 2004
    Сообщения:
    121
    Есть набор строк (количество строк не определено), длина строки ~1K, элементы строки могут принимать значение от 00 до FF.

    Вопрос, имеет ли смысл преобразовывать строку в хэш и сотрировать набор хэш-строк? И вообще, существуют ли алгоритмы хэширования, результат которых пригоден для сортировки? Или лучше не заморачиваться?

    <тема для меня новая, советы и ссылки приветствуются!>
     
  2. RobinFood

    RobinFood New Member

    Публикаций:
    0
    Регистрация:
    6 апр 2004
    Сообщения:
    45
    Адрес:
    Ukraine




    Не имеет. На вычисление хэша потратишь дополнительное время, а потом все равно будешь сортировать (хэши). Более того, для совпадающих хэшей придется сортировать именно строки.







    Конечно существуют. Например, хэш-функция, возвращающая первый символ строки. Короче говоря, алфавит :)
     
  3. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    IMHO для ускорения сортировки лучше 1м символом строки хранить длину строки / 4 (а может лучше длина_строки & 0xFF, зависит от самих строк). Это если ascii. Если символы 2х байтные, то просто длину строки. Тоже хеш, вроде алфавита :)
     
  4. blood

    blood New Member

    Публикаций:
    0
    Регистрация:
    21 ноя 2004
    Сообщения:
    56
    Адрес:
    Russia
    Хеши вроде бы и придумали для того, чтобы длинные ключи превращать в короткие... Хотя если строки сильно отличаются друг от друга первыми символами можно и просто сравнивать.
     
  5. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Чем тратить время на хэши, лучше составить таблицу указателей на строки и сортировать указатели, а не сами строки.
     
  6. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    cresta



    Ого. И как ты себе это представляешь?
     
  7. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    volodya





    Что вызвало сей вопрос? Как сортировать указатели? Или как составить таблицу указателей?
     
  8. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    Положим, у тебя есть три строки.



    "mama"

    "papa"

    "rama"



    теперь покажи мне, как ты будешь сортировать указатели.
     
  9. Edmond

    Edmond узник замка IF THEN ELSE

    Публикаций:
    0
    Регистрация:
    2 сен 2002
    Сообщения:
    203
    Адрес:
    WASM.RU
    volodya

    Мне кажется у тебя недавно была такая же задача



    Просто



    Массив указателей



    [1] -> b

    [2] -> a

    [3] -> c



    после сортировки



    [2]

    [1]

    [3]



    например



    Я верно написал?
     
  10. Edmond

    Edmond узник замка IF THEN ELSE

    Публикаций:
    0
    Регистрация:
    2 сен 2002
    Сообщения:
    203
    Адрес:
    WASM.RU
    const

    Вычислять кешь для такой строки - занятие скорее всего неблагодарное.

    Хотя наверно комбинированный вариант (вычисление хеша для части строки) возможно рулит.



    Мне кажется тут нужно что-то типа индексной сортировки.



    То есть берётся буква с строке, и она сразу "относится" с некоторым местом. И так по первой букве других строк.



    Но этот вариант по обращениям к памяти - проиграет - поэтому лучше придумать хитроумный хеш, который сделает подобную работу.



    То есть, о чём я говорю



    Есть N связанных списков, сгрупированные в массив по 256 элементов.



    то есть



    МАССИВ:


    Код (Text):
    1. [1] -> [указатель элемент] ->
    2. [2]
    3. [3]


    Мы берём букву, и помещаем указатель на строку в список, который относится к индексу массива, то есть



    если буква равна 1, то помещаем указатель в 1 элемент массива, вот так например


    Код (Text):
    1. [1] -> [указатель на строку,
    2.  которая начинается с 1] ->
    3. [2]
    4. [3]




    Потом тоже самое производится для второго символа всех строк, и так далее



    Прикол в том, что массив - всегда 1 %)



    Конечно описанный алгоритм - негодится, но сама идея может использоваться и развиваться.



    Дерзайте.
     
  11. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    volodya



    Допустим есть

    .data

    s1 db "mama",0

    s2 db "papa",0

    s3 db "rama",0



    1. Получаем кол-во строк (допустим 3)

    2. Выделяем (получаем) кусок памяти под таблицу размером 3 дворда

    3. В первые 4 байта по адресу таблицы записываем eax от lea eax,str1 (начало первой строки)

    4. Следующие 4 байта - начало второй строки

    5. Последние 4 байта - адрес последней строки



    Есть три дворда, они выстроены по возрастанию адресов строк. Т.е. Указатель_1...Указатель_3. Сами строки в беспорядке.

    6. Теперь берем любой алгоритм сортировки и переставляем указатели по такому принципу:

    7. mov esi, Указатель_1 (например, offset Table)

    mov edi, Указатель_2 (например, offset Table+4)

    lstrcmpi, esi,edi

    если eax > 0 то меняем в таблице первый и второй дворд местами.

    Строки 1 и 2 уже упорядочены между собой. При этом пересылается только два дворда. Сами строки где были в памяти, там и остались

    8. Продолжаем выбранный алгоритм, сравнивая строки, находящиеся по адресам, которые забиты в таблице, и продолжаем (при необходимости) менять местами эти адреса в таблице



    Для коротких строк, которые ты привел, сортировать указатели не имеет смысла. Смысл появляется для строк достаточно большой длины, например, как у автора 1кб. Т.к. переставлять две строки по 1 кб значительно дольше, чем переставить два дворда.

    После сортировки сам набор строк остался в неизменном виде, его никто не тасовал. А таблица приведена в состояние, при котором строка_по_offset+0 < строка_по_offset+4 < строка_по_offset+8..... и т.д.

    Теперь надо единственный раз пройти через набор строк, выбирая их по адресам от offset+0 до offset+8 и складывая в новую кучу, которая будет уже набором сортированных строк.



    Повторяюсь, на массиве из трех трехбуквенных строк этот метод лишён смысла. Он помогает при больших массивах и длинных строках
     
  12. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    Я понял тебя. Меня смутила первоначальная постановка вопроса и некорректно сформулированная фраза. Надо было говорить "сортировка поинтеров согласно значениям строк" или как-нибудь еще. Идея ничего.

    А вообще - мне больше всего нравится хеш-таблица. Так что идея с хеш-функцией без коллизий смотрится вполне неплохо. Просто const не сказал важной вещи - что будет происходить чаще - вставка или выборка.

    Есть и еще один интересный вариант, предложенный captain cobalt - ищите по форуму - где-то недалеко было...
     
  13. const

    const New Member

    Публикаций:
    0
    Регистрация:
    8 апр 2004
    Сообщения:
    121
    2 all прошу пардону, что не принял участия в обсуждении (Инет обрубили). Спасибо за советы...



    2 volodya

    1. А вообще - мне больше всего нравится хеш-таблица. Так что идея с хеш-функцией без коллизий смотрится вполне неплохо

    на данный момент мне тоже ближе хэширование (по крайней мере пока от такого подхода не отказался). Но из-за отсутствия подобающего опыта (и, если уж совсем честно - знаний) не могу подобрать "подходящую" функцию (без коллизий). С наскоку "закидать шапками" не получилось => надо врубать поосновательней. Гугл дает _огромное_ количество ссылок откровенно дилетантского содержания. Потому и решил поспрошать в форуме.

    2. Просто const не сказал важной вещи - что будет происходить чаще - вставка или выборка

    Выборка чаще... Есть желание разнести хэширование и сортировку по времени, т.е. получать хэш на втавке, и использовать уже готовый хэш при сортировке. Но пока это не принципиально...

    3. Есть и еще один интересный вариант, предложенный captain cobalt - ищите по форуму - где-то недалеко было...

    Перед созданием темы попробовал поискать по форуму, но, видать, руки кривоваты... Попробовал и счас поискать - тоже что-то не нашел. >:о(

    2 cresta

    Я правильно понял - предлагается перемещать не сами строки, как это делается в обычной сортировке, а указатели на строки, предварительно сравнивая эти строки?

    Интересный подход, но настораживает следующее. Сравнить 2 строки - несложно, переместить указатели - тоже понятно. Но ведь нужно еще и сравнить полученный результат с результатами предыдущих итераций. Т.е. мало знать, что строка_1000 > строка_1001, нужно еще (чтобы корректно разместить указатель) знать, что строка_1000 больше строк 5,15,98,586, но меньше строка_503. не будет ли потери эффективности из-за таких сравнений? Или такой подход уже вами используется, и я зря опасаюсь?
     
  14. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    const







    Совершенно верно. И опасения совершенно напрасны :) То что я привел, всего лишь сравнение двух строк. Фрагмент из общего процесса. Но ведь сортировка не ограничивается перестановкой двух строк. Как в любом алгоритме сортировки, ты будешь продолжать сравнения (и перестановки при необходимости) всей кучи строк, пока строки (или указатели) не будут упорядочены. Я привел только как упорядочить две строки между собой. Чтобы был понятен принцип работы.

    Количество сравнений\перестановок одинаково, с указателями или без. Упрощается(ускоряется) перестановки, т.к. два дворда переставить значительно быстрее, чем две строки.



    P.S.

    Это не есть алгоритм сортировки. Алгоритм может быть любым, его выбирай исходя из своих условий. Я применял такой принцип (сортировка указателей) на практике, ничего страшного нет в этом.
     
  15. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    не могу подобрать "подходящую" функцию (без коллизий)



    дык, есть специальные функции, называемые криптографическими, вот они без коллизий работают. только очень медленно.

    а целый ряд обычных, вполне нормальных хаш-функций я приводил тут:



    http://www.wasm.ru/forum/index.php?action=vthread&forum=17&topic=5348
     
  16. const

    const New Member

    Публикаций:
    0
    Регистрация:
    8 апр 2004
    Сообщения:
    121
    2 cresta, volodya

    Большая сенька! беру тайм-аут на переваривание...
     
  17. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    volodya



    Порылся в msdn, но не нашёл ответ на такой вопрос:

    если строка1 меньше чем строка2, то всегда ли хэш от строки1 будет также меньше хэша от строки2?

    И ещё: о длине хэш-данных нашёл только это:

    HASH - это длинная строка из набора символов '0123456789ABCDEF'. Всего таких символов в HASH'е - ровно 32 штуки.

    Значит получается сравнивать придется все равно строки. длиной 32 байта?
     
  18. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    стоп-стоп-стоп... не путай грешное с праведным.

    еще раз



    если строка1 меньше чем строка2, то всегда ли хэш от строки1 будет также меньше хэша от строки2?





    1. "строка1 меньше чем строка2" - видимо, надо понимать фразу как "длина строки1 меньше, чем длина строки2"

    2. "хэш от строки1 будет также меньше хэша от строки2" - хеш - это число и сравниваем мы два числа.



    И вопрос бессмысленнен без хеш-функции - каждая хеш-функция вычисляет хеш по-разному и вовсе не факт, что хеш меньшей по длине строки будет численно меньше. Он может быть и больше!
     
  19. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Ну а если нет такой однозначной зависимости, то как можно сортировать по хэш-строкам? Если отсортированы хэш-строки, то исходные строки могут ведь оказаться (и исходя из сказанного тобой, наверняка окажутся) несортированными.

    Или я че-то недопонял :dntknw: Получается как сказал RobinFood в первом ответе, что вычислять хэши, чтобы сортировать строки - бессмысленно?



    Вот две строки, сортированые по возрастанию:

    "аааббб"

    "ааабббввв"

    Всегда ли хэш первой строки будет меньше хэша второй строки? Если нет, какой смысл применения хэша для сортировки строк? По-моему смысла нет.



    Или вот такие строки:

    "абвгде"

    "абвгдя"

    Опять же, будет ли хэш1 всегда меньше хэша2
     
  20. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    Если нет, какой смысл применения хэша для сортировки строк? По-моему смысла нет.



    Нет, если использовать напрямую - в лоб, как думаешь ты.

    Хеш можно использовать как вспомогательную величину, т.к. удобнее сравнивать два int, чем два char *. А вообще, я изначально думал о

    http://rsdn.ru/article/alg/bintree/hash.xml