Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Синтаксис
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 12.02.2015, 15:17
Аватар для SCrat.ORS
SCrat.ORS SCrat.ORS вне форума
Активный
 
Регистрация: 20.02.2007
Адрес: Мой адрес не дом и не улица, мой адрес 0x7С00
Сообщения: 208
Версия Delphi: 2006
Репутация: 884
Вопрос Поиск строки в массиве из N элементов

Собственно вопрос в названии. Дан массив из n элементов:
Код:
var
mas: array of string;
Нужно найти номер элемента массива в котором содержится искомая строка.
Реально ли организовать поиск не перебирая все элементы?
Код:
function Find(const AText: string; const AValues: array of string): Integer;
var
  I: Integer;
begin
  Result := -1;
  for I := Low(AValues) to High(AValues) do
    if AText=AValues[i] then
    begin
      Result := I;
      Break;
    end;
end;
Есть ли способ быстрее?
__________________
Програмистами не рождаются, ими становятся!
Ответить с цитированием
  #2  
Старый 12.02.2015, 15:44
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию

Если список сортированный, то можно сделать чтобы искало логарифмически быстро.
__________________
— Как тебя понимать?
— Понимать меня не обязательно. Обязательно меня любить и кормить вовремя.


На Delphi, увы, больше не программирую.
Рекомендуемая литература по программированию
Ответить с цитированием
  #3  
Старый 12.02.2015, 16:06
Аватар для SCrat.ORS
SCrat.ORS SCrat.ORS вне форума
Активный
 
Регистрация: 20.02.2007
Адрес: Мой адрес не дом и не улица, мой адрес 0x7С00
Сообщения: 208
Версия Delphi: 2006
Репутация: 884
По умолчанию

Если в массиве записаны и отсортированы числа, то да.
А если там записаны слова, тут я не понимаю сути поиска, даже если отсортировать по алфавиту.
M.A.D.M.A.N., Можешь показать функцию поиска?
__________________
Програмистами не рождаются, ими становятся!
Ответить с цитированием
  #4  
Старый 12.02.2015, 16:49
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию

Символ строки есть число. Берешь середину массива, первую букву, если искомая больше этой, то берешь правую половину массива, повторяешь до тех пор, пока не дойдешь до искомой строки.
__________________
— Как тебя понимать?
— Понимать меня не обязательно. Обязательно меня любить и кормить вовремя.


На Delphi, увы, больше не программирую.
Рекомендуемая литература по программированию
Ответить с цитированием
  #5  
Старый 12.02.2015, 21:53
Аватар для SCrat.ORS
SCrat.ORS SCrat.ORS вне форума
Активный
 
Регистрация: 20.02.2007
Адрес: Мой адрес не дом и не улица, мой адрес 0x7С00
Сообщения: 208
Версия Delphi: 2006
Репутация: 884
По умолчанию

Хорошо, а если у меня много строк, которые начинаются с одинаковых букв, ибо в массиве не 1 буква записана, а слово.
Попадаю в ситуацию, с левого краю нужные буквы и с правого краю нужные буквы, я так понимаю начинаем искать по второй букве, и тут второй вопрос, - может получиться что во вновь делимой половине, окажется что слова и требуемой первой буквой находятся не с начала и не до конца, а в центре т.е. начинаю искать по второй букве и случайно она может совпать с теми которые вначале-вконце, а значит первая букава не совпадает... так много IF в этом алгоритме. Даже боюсь предположить как реализовывать
__________________
Програмистами не рождаются, ими становятся!

Последний раз редактировалось SCrat.ORS, 12.02.2015 в 21:57.
Ответить с цитированием
  #6  
Старый 12.02.2015, 22:16
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию

http://www.swissdelphicenter.ch/torr...de.php?id=1916
Код:
function BinSearch(Strings: TStringArray; SubStr: string): Integer;
var
  First: Integer;
  Last: Integer;
  Pivot: Integer;
  Found: Boolean;
begin
  First  := Low(Strings); //Sets the first item of the range
  Last   := High(Strings); //Sets the last item of the range
  Found  := False; //Initializes the Found flag (Not found yet)
  Result := -1; //Initializes the Result

  //If First > Last then the searched item doesn't exist
  //If the item is found the loop will stop
  while (First <= Last) and (not Found) do
  begin
    //Gets the middle of the selected range
    Pivot := (First + Last) div 2;
    //Compares the String in the middle with the searched one
    if Strings[Pivot] = SubStr then
    begin
      Found  := True;
      Result := Pivot;
    end
    //If the Item in the middle has a bigger value than
    //the searched item, then select the first half
    else if Strings[Pivot] > SubStr then
      Last := Pivot - 1
        //else select the second half
    else 
      First := Pivot + 1;
  end;
end;
__________________
— Как тебя понимать?
— Понимать меня не обязательно. Обязательно меня любить и кормить вовремя.


На Delphi, увы, больше не программирую.
Рекомендуемая литература по программированию

Последний раз редактировалось M.A.D.M.A.N., 12.02.2015 в 22:47.
Ответить с цитированием
  #7  
Старый 12.02.2015, 22:16
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Вопрос был - "можно ли организовать поиск, не перебирая все элементы". Ответ: можно в сортированном (хотя бы по первым буквам) массиве.
Простейший вариант:
Идем по массиву, ищем первую букву.
Код:
i := 0;
while i < length(arr) do
begin
   if arr[i][0] > s[0] then
   begin
     i := length(arr);
     break;
   end;
   if arr[i][0] = s[0] then
     break;
   i := i + 1;
end;
if i >= length(arr) then exit; // нет строки
Либо дошли до конца, либо нашли индекс первой строки, в которой совпадает первая буква.
Далее ищем саму строку, пока первые символы совпадают:
Код:
while i < length(arr) do
begin
   if arr[i][0] > s[0] then
   begin
     i := length(arr);
     break;
   end;
   if arr[i] = s then
   begin
     foundIndex := i;
     break;
   end;
   i := i + 1;
end;
Теперь foundIndex содержит номер строки.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
  #8  
Старый 13.02.2015, 09:27
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

Ну посмотрите реализацию TStringList.
Или сразу используйте именно его.
Ответить с цитированием
  #9  
Старый 13.02.2015, 10:21
Аватар для SCrat.ORS
SCrat.ORS SCrat.ORS вне форума
Активный
 
Регистрация: 20.02.2007
Адрес: Мой адрес не дом и не улица, мой адрес 0x7С00
Сообщения: 208
Версия Delphi: 2006
Репутация: 884
По умолчанию

Результаты тестирования.

Массив 1 700 слов, 10000 циклов поиска первой, средней, последней строки.
1. Тупо перебор по всем строкам: 0,0073 мсек.
2. Бинарный поиск: 0,0656 мсек.
3. (Не знаю как назвать): 0,0036 мсек.
4. TStringList.IndexOf: 0,2713 мсек.

Массив 170 000 слов, 1000 циклов поиска первой, средней, последней строки.
1. Тупо перебор по всем строкам: 1,119 мсек.
2. Бинарный поиск: 11,93 мсек. !!!!
3. (Не знаю как назвать): 1,114 мсек.
4. TStringList.IndexOf: 27,81 мсек.

Массив 1 700 000 слов, 100 циклов поиска первой, средней, последней строки.
1. Тупо перебор по всем строкам: 12,55 мсек.
2. Бинарный поиск: Error (Stack Overflow)
3. (Не знаю как назвать): 11,71 мсек.
4. TStringList.IndexOf: 275,88 мсек.

Время указано среднее на 1 поиск.

Значит получается что эффективнее всего использовать тупо перебор всех строк, так как он по времени не на много отстает от лидера, но его преимущество в том, что массив не нужно сортировать, а соответственно не затрачивается время на сортировку.
__________________
Програмистами не рождаются, ими становятся!

Последний раз редактировалось SCrat.ORS, 13.02.2015 в 11:57.
Ответить с цитированием
  #10  
Старый 13.02.2015, 13:37
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию

Значит так и делай.
__________________
— Как тебя понимать?
— Понимать меня не обязательно. Обязательно меня любить и кормить вовремя.


На Delphi, увы, больше не программирую.
Рекомендуемая литература по программированию
Ответить с цитированием
  #11  
Старый 13.02.2015, 16:45
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

А StringList в Ваших тестах - сортированный?
Ответить с цитированием
  #12  
Старый 13.02.2015, 17:33
Аватар для madMonia
madMonia madMonia вне форума
Новичок
 
Регистрация: 25.02.2014
Сообщения: 50
Версия Delphi: Delphi XE3
Репутация: 2545
По умолчанию

Какие-то странные у вас результаты. Бинарный поиск - это то, что предложил M.A.D.M.A.N, и он должен значительно быстрее работать, чем простой перебор. И уж точно не должен возвращать Stack Overflow. А что за алгоритм "не знаю как назвать".
__________________
Невозможно заточить карандаш тупым топором. Столь же тщетно пытаться сделать это десятком тупых топоров

Последний раз редактировалось madMonia, 13.02.2015 в 17:40.
Ответить с цитированием
  #13  
Старый 13.02.2015, 20:11
Аватар для SCrat.ORS
SCrat.ORS SCrat.ORS вне форума
Активный
 
Регистрация: 20.02.2007
Адрес: Мой адрес не дом и не улица, мой адрес 0x7С00
Сообщения: 208
Версия Delphi: 2006
Репутация: 884
По умолчанию

Массив используется сортированный, а значит и StringList тоже.
Результаты показаны по функциям представленных в постах, без изменений алгоритма.
(Не знаю как назвать) - это алгоритм предложенный Bargest
__________________
Програмистами не рождаются, ими становятся!

Последний раз редактировалось SCrat.ORS, 13.02.2015 в 20:15.
Ответить с цитированием
  #14  
Старый 13.02.2015, 20:24
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,057
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Поищи еще реализацию HashMap'а.
Ответить с цитированием
  #15  
Старый 13.02.2015, 20:59
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Цитата:
Значит получается что эффективнее всего использовать тупо перебор всех строк
Просто на всякий случай, использовались не те же самые строки, что лежали в массиве? Я к тому, что не получилось ли так, что в тесте строка находилась по совпадению указателя на строку, а не самой строки?
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 20:51.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter