|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#16
|
||||
|
||||
Цитата:
Я не знаю как ты тестил, но код, который я привел в примере, 1000 итераций на файле 66 852 700 байт (1 591 731 строк) выполняет мгновенно, за 0,00118835431432329 сек. 10000 итераций за 0,0126044552868083 сек. Разовый поиск за 6,84213423583157E-6 сек. — Как тебя понимать? — Понимать меня не обязательно. Обязательно меня любить и кормить вовремя. На Delphi, увы, больше не программирую. Рекомендуемая литература по программированию Последний раз редактировалось M.A.D.M.A.N., 13.02.2015 в 22:44. |
#17
|
||||
|
||||
Bargest, Нет строки разные, поиск шёл по слову.
M.A.D.M.A.N. Я просто взял массив array of string, который динамически расширял и заносил сортированный список. Функцию поиска просто скопипастил, единственно заменил TStringArray на array of string, т.к. у меня массив использовался, если быть точным MASS : array of array [0..2] of string (да, такой вот странный) и на функцию подавал MASS[0] . Затем поставил GetTickCount и запустил цикл поиска 10000 раз по первому слову в массиве, слову в середине массива, и последнему слову в массиве, GetTickCount снимал после циклов поиска каждого слова. После чего вывел среднее арифметическое из 3 результатов, аналогично для разных длин массива. А теперь об ошибке, - когда я передал функции массив длинной 1 700 000, он выбил Ошибку. И еще, обрати внимание, я время указывал в Миллисекундах. Опять таки, возможно, я использовал на форме, а у вас возможно в консоли. Возможно комп слабее/мощнее. Что бы было нагляднее, проведи тестирование тоже всех 4 видов... Конечно я согласен, что тупо перебор слово в первой строке найдет мгновенно, а последнее слово - чем больше массив тем дольше,.. Ясен перец Бинарный поиск в огромном массиве найдет в разы быстрее, но у меня почему-то результат обратный - наверное что-то не так сделал - не отрицаю, сам был удивлён. Програмистами не рождаются, ими становятся! Последний раз редактировалось SCrat.ORS, 13.02.2015 в 23:14. |
#18
|
||||
|
||||
Цитата:
jmp $ ; Happy End! The Cake Is A Lie. |
#19
|
||||
|
||||
Цитата:
Комп 4 ядра, тестировал на форме, вместо «счетчика клещей», я использовал «перформанс каунтер». По поводу тайминга: Код:
10^−1 деци 10^−2 санти 10^−3 милли 10^−6 микро 10^−9 нано 10^−12 пико 10^−15 фемто 10^−18 атто 10^−21 зепто 10^−24 иокто — Как тебя понимать? — Понимать меня не обязательно. Обязательно меня любить и кормить вовремя. На Delphi, увы, больше не программирую. Рекомендуемая литература по программированию Последний раз редактировалось M.A.D.M.A.N., 14.02.2015 в 08:57. |
#20
|
||||
|
||||
Все-таки в моём понимании массив - это array а не StringList...
А почему в бинарном поиске у меня вылезает ошибка стека при большом количестве записей - не понимаю... другие то функции ошибки не вызывают. Програмистами не рождаются, ими становятся! |
#21
|
||||
|
||||
Чем вообще обусловлен выбор array?
— Как тебя понимать? — Понимать меня не обязательно. Обязательно меня любить и кормить вовремя. На Delphi, увы, больше не программирую. Рекомендуемая литература по программированию |
#22
|
||||
|
||||
Ну изначально вопрос встал так:
У меня есть какой-то файл, в котором содержится информация об каких-либо свойствах объектов, а именно - название, длина, ширина, который я загружаю в один array. Так же имеется список, скажем выставленных объектов на карту (пусть так), где записано, ИД объекта, его координаты (x,y) и название объекта, которые я загружаю в другой array, и непосредственно с этим массивом работаю. И при отрисовке объекта на карте мне надо получить его длину и ширину. И тут вызываю поиск по массиву с информацией - передаю название объекта, на выходе получаю длину и ширину (пусть в TPoint, - не суть)... поэтому и получается что использовать StringList как-то не правильно. А список выставленных объектов иногда может переваливать за несколько тысяч, а то и десятков тысяч... Идея такова. Да и по жизни я стараюсь использовать array of myTypes для запоминания свойств объектов. Когда реализовывал задачу, я подумал, что перебор по всем строкам массива будет очень медленным способом поиска и сделал кроме основного массива с информацией еще и stringList, где в том же порядке записал просто названия объектов, а далее при работе просто вызывал IndexOf и получал нужный мне индекс. Потом по этому индексу брал из массива информацию. Теперь, как я понял, я выбрал самый тормознутый способ. В любом случае Пост получился довольно интересным для меня, за что всем принявшим участие в нем - огромное спасибо. Конечно хочется развить тему дальше и найти самый продуктивный способ как поиска так и хранения свойств каких-либо объектов (частенько требуется). Програмистами не рождаются, ими становятся! Последний раз редактировалось SCrat.ORS, 14.02.2015 в 14:09. |
#23
|
||||
|
||||
Цитата:
— Как тебя понимать? — Понимать меня не обязательно. Обязательно меня любить и кормить вовремя. На Delphi, увы, больше не программирую. Рекомендуемая литература по программированию |
#24
|
||||
|
||||
Цитата:
Есть множество объектов на карте. У каждого есть уникальный ID. Зачем передавать название объекта, когда можно передавать ID? Если по названию находится не сам объект, а его прототип (общий для нескольких объектов), то что мешает в массиве объектов хранить не имя, а индекс прототипа или (лучше) сразу указатель на него и не искать ничего вообще? Нужно просто нормально организовать данные. Если нужно отрисовать объект, то отрисовка должна происходить не по имени, а по индексу/указателю. Также должно быть можно через индексы/указатели от объекта добраться ко всем данным, которые могут потребоваться для отрисовки. Даже известный мне шедевр игрового убожества, наглядное пособие "как НЕ надо писать игры", и те не додумались каждые 20мс брутфорсить 10к строк, а просто посчитали от имени 4-байтовый хеш, запихнули в хеш-таблицу по первым двум байтам и положили болт на потенциальные коллизии, т.е. у них во время выполнения имен фактически нет вовсе. Не говоря уже о том, что для отрисовки не используется даже ID - он им нужен по-моему только для интегрированных скриптов. jmp $ ; Happy End! The Cake Is A Lie. Последний раз редактировалось Bargest, 14.02.2015 в 16:42. |
#25
|
||||
|
||||
Цитата:
Сначала загружаю информацию о "протопитах" в отдельный массив. Потом в рабочий массив загружаю информацию об объектах, тут же попутно нахожу "протопип" по названию, и подгружаю туда же нужную информацию о "прототипе". Т.Е. поиск мне необходим только при первом запуске, что бы получить всю нужную информацию. И потом в процессе работы никакго поиска не произвожу вообще. Програмистами не рождаются, ими становятся! |
#26
|
||||
|
||||
Цитата:
Цитата:
То есть просто копипастим с вики crc8/crc16/crc32, берем младшие 1-2 байта результата, используем как индекс в массиве динамических списков. Каждый N-ный элемент - список прототипов, хеш от имени которых начинается на N. Поскольку хеши стремятся к равномерному "распределению", то таблица будет заполняться равномерно, и в среднем поиск будет производиться не среди 10к строк, а среди 10к/256 или 10к/65536 строк если брать 1 или 2 байта хеша соответственно. А можно взять и 1.5 байта хеша и будет поиск среди 10к/4096, т.е. в среднем среди двух строк. И кстати, я бы сделал наоборот. Сарзу загружаю информацию об объектах, ищу для них по хеш-таблице прототип, и если не найден - загружаю прототип и добавляю в хеш-таблицу. Это позволит загружать только нужные прототипы, а не все (ведь на одной карте могут использоваться не все прототипы). jmp $ ; Happy End! The Cake Is A Lie. Последний раз редактировалось Bargest, 14.02.2015 в 17:14. |
#27
|
||||
|
||||
Цитата:
Програмистами не рождаются, ими становятся! |
#28
|
||||
|
||||
Можно конечно и свой велосипед придумать, но есть готовые решения, считаемые легко и довольно удобно. Я обычно использую табличные варианты. Из простых есть еще известный ror13-хеш:
Код:
hash := 0; for i := 1 to length(str) do hash := ((hash shl (32-13)) or (hash shr 13)) + str[i]; При удалении в данном случае достаточно опять же найти нужный элемент и исключить из соответствующего списка. И вообще, вот. jmp $ ; Happy End! The Cake Is A Lie. Последний раз редактировалось Bargest, 14.02.2015 в 17:37. |
#29
|
||||
|
||||
Просто оставлю это здесь
Код:
// Name : CRC-8 // Poly : 0x31 x^8 + x^5 + x^4 + 1 // Init : 0xFF // Revert: false // XorOut: 0x00 // Check : 0xF7 ("123456789") function crc8(Buffer:String):byte; var i,j: Integer; begin Result:=$FF; for i:=1 to Length(Buffer) do begin Result:=Result xor ord(buffer[i]); for j:=0 to 7 do begin if (Result and $80)<>0 then Result:=(Result shl 1) xor $31 else Result:=Result shl 1; end; end; end; Програмистами не рождаются, ими становятся! |
#30
|
||||
|
||||
Bargest, спасибо за наводку.
Результат: 2 000 000 Строк, 100 000 циклов поиска: Среднее время поиска 0,078 мсек. Результат Бинарного поиска от M.A.D.M.A.N. (который мне не удалось сделать, поэтому результат его) 12,6 мсек. (0,0126044552868083 сек). Это конечно несколько разные подходы к организации массивов и поиска, но ради интереса. Так что да,.. хранить нужно с хешем. M.A.D.M.A.N. Твой результат в мсек. примерно тоже самое что у меня и показывает. Так что все более менее одинаково и твои Мгновенно - это и есть 11 мсек. Вероятно Бинарный поиск дает свои плоды если количество слов более 10млн, т.к. до 2 млн, он по вычислениям почти совпадает с Простым перебором. Вот такое вот исследование. Вот как реализовал: Код:
... Type TMyArray = Packed Record SomeName:String; end; Type MyArray = array [$00..$FF] of Array of TMyArray; ... function crc8(Buffer:String):byte; var i,j: Integer; begin Result:=$FF; for i:=1 to Length(Buffer) do begin Result:=Result xor ord(buffer[i]); for j:=0 to 7 do begin if (Result and $80)<>0 then Result:=(Result shl 1) xor $31 else Result:=Result shl 1; end; end; end; function FindM(const AText: string; const AValues: array of TMyArray): Integer; var I: Integer; begin Result := -1; for I := Low(AValues) to High(AValues) do if AText=AValues[i].SomeName then begin Result := I; Break; end; end; Function Find(S:String; M: MyArray):TPoint; Var NDX:Integer; Begin NDX:=CRC8(s); Result.X:=NDX; Result.Y:=FindM(s,M[NDX]); End; ... procedure TForm1.Button1Click(Sender: TObject); Var I:TPoint; N:String; begin I:=Find('СТРОКА ПОИСКА', MItemInformation); //MItemInformation - Это массив в котором ищем If i.Y>-1 then N:=MItemInformation[I.X,I.Y].SomeName; end; Програмистами не рождаются, ими становятся! Последний раз редактировалось SCrat.ORS, 14.02.2015 в 19:37. |