Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Общие вопросы по программированию, компьютерный форум
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 21.06.2016, 10:51   #1
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию Оптимизация доступа к данным в деревьях

Итак, есть дерево строк (по предыдущим темам должно быть понятно). Ну например:
Планета
...Континенты
......Азия
......Европа
.........Москва
......Южная Америка
......Северная Америка
......Австралия
...Океаны
......Тихий океан
......Атлантический океан
......Индийский океан

Все узлы физически размещены в динамическом массиве. Для поиска узлов используется идентификатор (так как элементы могут удаляться идентификатор узла и его индекс в массиве это разные вещи). Суть проблемы ранее уже озвучивали, но мне не когда было ранее обращать на это внимание. Теперь же вот например я хочу добавить Москве в угоду админу вон Химки. Соответственно рекурсивно - нужно преобразовать строковое имя в идентификатор, а по нему в индекс. Все это делается пока что простым перебором. Проблема в том что сразу индекс элемента массива получить нельзя, так как имена у различных ветвей на разных уровнях могут повторяться. То есть нужно строить всю цепочку последовательно: Планета-Континенты-Европа-Москва. То есть я должен как минимум 4 раза перебирать массив, а если Москву добавляли последней, то как минимум один раз полностью пройти его.
Вопрос как ускорить процесс? Мне нужно быстро получить идентификатор или индекс для элемента Москва. Пока ничего не придумал, только сделать по уровням привязку имен/идентификаторов (помним, что элементы в массиве могут менять местоположение, потому сразу индексы непонятно как прикрутить). Ну то есть где-то хранить Планета(0 - идентификатор, 0 - начальный уровень) и т.д. В пути уровень определить уже можно и так ускорить построение пути до нужного идентификатора, а там уже полным перебором в массиве найти нужный индекс.
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Старый 21.06.2016, 11:10   #2
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

А узлы просто строки или объекты? Если объекты, то почему бы не искать по ссылкам на дочерние? Ссылочки конечно в объект придется встраивать
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 21.06.2016, 11:14   #3
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Цитата:
Вопрос как ускорить процесс?
Использовать поиск в дереве, а не в линейном массиве.

Цитата:
а если Москву добавляли последней, то как минимум один раз полностью пройти его.
Кешируй последний запрос. Хранишь последний индекс выдачи.
Если он совпадает с подзапросом из нового запроса, то поиск начинай от него.

Индексировать надо то по чему у вас чаще идут запросы.

А вообще вам надо начинать с архитектуры. Опишите данные их объемы. Напишите какой вид операций чаще используется: вставка, удаление или поиск. Выберете из сходя из этого нужную коллекцию(динамическую структуру).
Для оптимизации используйте индексы и кеши, которые должны ускорить работу выбранной коллекции данных под конкретные разновидности запросов.
И помните золотое правило программиста: выигрываешь в скорости проигрываешь в памяти.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .

Последний раз редактировалось Pavia; 21.06.2016 в 11:22.
Pavia вне форума Ответить с цитированием
Старый 21.06.2016, 11:39   #4
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Цитата:
А узлы просто строки или объекты?
Это записи. Они хранят информацию о родителе и дочерних узлах. Но такая структура при поиске элементов заставляет рекурсивно для каждого шага перебирать массив.
Цитата:
Кешируй последний запрос. Хранишь последний индекс выдачи.
А если предпоследний? Это нельзя предсказать заранее.
Цитата:
Индексировать надо то по чему у вас чаще идут запросы.
К корневому узлу. Его индекс я и так знаю.
Цитата:
Опишите данные их объемы.
Объемы неизвестны как выглядит написал в пером посте.
Код:
// Описание структуры узла
type
    TSNode = record

           Name: String;             // Имя узла
           Parent: Integer;          // Индекс родителя
           Value: String;            // Строковое значение узла
           Childs: TIntList;         // Индексы дочерних узлов
           ID: Integer;              // Собственный идентификатор узла
    end;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
В хранилище всех узлов/деревьев есть такая беда:
Код:
          // Поля класса
          Nodes: Array of TSNode;                                                               // Набор узлов
          IdFree: Integer;                                                                      // Свободный идентификатор
          DeletedId: TIntList;                                                                  // Список удаленных
Цитата:
Напишите какой вид операций чаще используется: вставка, удаление или поиск.
Доступ к элементу. Например хочу Москву в Австралию перенести. Так вот ее сначала нужно найти. Точней найти ее непосредственного родителя в массиве, потом найти приемник, то есть Австралию в массиве узлов и только потом уже выполнить операцию перемещения.
Цитата:
Для оптимизации используйте индексы и кеши, которые должны ускорить работу выбранной коллекции данных под конкретные разновидности запросов.
Вот про это и тема. Представьте что в том примере карта городов всего мира. Поиск Москвы в таком массиве элементов займет ого-го сколько времени, так как операция рекурсивна - алгоритм спускается по дереву вниз и каждый узел в массиве ищется заново. В идеально лажовом варианте, время поиска займет примерно факториал от числа элементов. Мне нужно это ускорить. Потому что даже если среднее время поиска будет факториал от половины элементов - это все равно много. Тут для 100 элементов вырисовывается степень в 50, а мне это не нравится.
Цитата:
И помните золотое правило программиста: выигрываешь в скорости проигрываешь в памяти.
Пофиг. Сейчас критична именно скорость, поскольку вся суть вычислительных процессов будет замешана на поиске одно-двух элементов в дереве и работе с ними. Так вот и получается что поиск элемента значительно превосходит саму операцию. Мне это не нравится и чувствуется отсутствие гармонии в жизни.
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика

Последний раз редактировалось Utkin; 21.06.2016 в 11:54.
Utkin вне форума Ответить с цитированием
Старый 21.06.2016, 11:52   #5
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

А чего на родителя и детей индексы, а не Pointer? Тогда положение в массиве не важно будет. Да и сам массив не очень актуален.
Цитата:
Например хочу Москву в Австралию перенести. Так вот ее сначала нужно найти. Точней найти ее непосредственного родителя в массиве, потом найти приемник, то есть Австралию в массиве узлов и только потом уже выполнить операцию перемещения.
Москву искать не нужно, она уже есть в родителе, а указатель на Австралию задать, ведь клик по ней по крайней мере перед перемещением. Если поиск по наименованию - кроме перебора по дереву ни чего более умного не приходит в голову
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию

Последний раз редактировалось Аватар; 21.06.2016 в 11:56.
Аватар вне форума Ответить с цитированием
Старый 21.06.2016, 12:05   #6
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Цитата:
Тогда положение в массиве не важно будет.
Там указывается идентификатор узла, а не индекс в массиве. Там в первом посте немного написано. То есть своя относительная адресация, поверх физической реализации.
Цитата:
Москву искать не нужно, она уже есть в родителе, а указатель на Австралию задать
А родитель где? Его нужно найти сначала. А чтобы найти родителя нужно найти родителя родителя. Это как:
Цитата:
Авраам родил Исаака; Исаак родил Иакова; Иаков родил Иуду и братьев его;
Иуда родил Фареса и Зару от Фамари; Фарес родил Есрома; Есром родил Арама;
Нельзя напрямую взять Европу и отжать у нее Москву. Европу тоже сначала надо найти, потому что имена не уникальны. То есть они уникальны в рамках одного родителя, а в разных уровнях могут повторяться.
Цитата:
По другому - искать перебором по дереву
Вот сейчас так и ищется. Берется корневой узел Планета, в ней ищется Континенты. Потому что юзер мог ошибиться и написать например Материки, а это лажа. Поэтому мы сначала должны убедиться что на планете вообще есть континенты. Потом среди названий континентов ищется Европа по той же схеме - мы должны быть уверены, что на нашей планете есть Европа - структура динамическая и сегодня Европа на карте есть, а завтра нету - кто знает? И так далее. Все это оборачивается длительными забегами на дальние дистанции по массиву узлов. Первый раз найди им Европу, второй раз найди Австралию. В следующей операции могут ведь Токио добавить - опять перебор, чтобы удостовериться что Азия вообще есть на планете. А представьте потом раз и стерли Европу - это опять каскад событий.
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Старый 21.06.2016, 12:07   #7
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Utkin
Вам надо посмотреть на проблему глобально. Вы сейчас ищете локальное решение. Это не даст вам решения, будет как в анекдоте:
Хвост поднял - нос увяз.
Нос поднял - хвост увяз!

Цитата:
А если предпоследний? Это нельзя предсказать заранее.
Можно. Статистика вещь сильная.

Цитата:
Объемы неизвестны как выглядит написал в пером посте.
Так оцените: топонимов у нас в России 10 000 тысяч. 100 стран мира. = 1 милион. По вселенной пусть 2 миллиона.
Т.е. не больше 10 миллионов.

Цитата:
Доступ к элементу. Например хочу Москву в Австралию перенести. Так вот ее сначала нужно найти.
Так поиск или доступ? Если доступ почему тема про поиск?
Зачем вам делать поиск? Кто ищет человек или машина? Если человек ему главное уложиться <1 секунды. Это выполняется в линейном списке при линейном поиске.
А у вас есть дерево вот и делайте обход дерева в глубину или в ширину.
Будет в 1000-1 000 000 быстрее линейного поиска. И тут вы гарантированно уложитесь.

Если поиск это делает машина, то она делает по некоторым входным данным. Вот коллекцию надо подстраивать под структуру этих данных.

Храните полный путь 'Планета.Континенты.Азия.Европа.Мос ква' в линейном отсортированном списке. Можно будет искать бинарным поиском.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .
Pavia вне форума Ответить с цитированием
Старый 21.06.2016, 12:12   #8
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Цитата:
А родитель где? Его нужно найти сначала. А чтобы найти родителя нужно найти родителя родителя. Это как:
Выкиньте все и сделайте по нормальному. Если у вас доступ происходит чаще всего надо хранить не идентификатор, а индекс от массива.
И будет ваша операция O(1)
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .

Последний раз редактировалось Pavia; 21.06.2016 в 12:36.
Pavia вне форума Ответить с цитированием
Старый 21.06.2016, 12:12   #9
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Так и я к тому - вместо не понятных индексов родителя и детей их адреса. Я об этом
Код:
type PMyRecord = ^TMyRecord;
     TMyRecord = record
       Text: String;
       Parent: PMyRecord;
       Childrens: array of PMyRecord;
     end;
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 21.06.2016, 12:46   #10
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Цитата:
Так оцените: топонимов у нас в России 10 000 тысяч. 100 стран мира. = 1 милион. По вселенной пусть 2 миллиона.
Т.е. не больше 10 миллионов.
Пусть будет от нуля до 10 лямов.
Цитата:
Так поиск или доступ? Если доступ почему тема про поиск?
В данном случае это одно и тоже.
Цитата:
Зачем вам делать поиск? Кто ищет человек или машина?
Ищет машина. Но по указке человека.
Цитата:
А у вас есть дерево вот и делайте обход дерева в глубину или в ширину.
Да блин это и есть рекурсия типичная. То есть медленно.
Цитата:
Если поиск это делает машина, то она делает по некоторым входным данным. Вот коллекцию надо подстраивать под структуру этих данных.
Я привел образец. Там может быть все что угодно - генеалогическое дерево, информационная система, периодическая таблица Менделеева. Там может быть многомерный массив. Куб данных например. Вот и подстройте попробуйте.
Цитата:
Если у вас доступ происходит чаще всего надо хранить не идентификатор, а индекс от массива.
Я уже писал про удаление! Удалили элемент из середины массива и? Все индексы съехали к чертям собачим . Причем не линейно, так как возможны все операции - перемещение одной ветви в другую, удаление узла (а если он имеет дочерние то и всю ветвь) и т.д. В результате Вам нужно будет удалить по массиву там и сям кучу элементов, какие и как неизвестно. Ну и как Вам просто индексы помогут? Вы как перемещать например по индексам будете? Физически элементы в массиве перестраивать?
Цитата:
И будет ваша операция O(1)
В дереве? Ага, размечтались.
Цитата:
вместо не понятных индексов родителя и детей их адреса.
Не индексов, а идентификаторов.
Цитата:
Я об этом
Проблема осталась. Попробуйте Вашими структурами переместить Москву в Австралию. Вы просто смотрите на другом уровне абстракции, но алгоритм реализуется для дерева - стало быть не меняет своей сути и сложности процесса. А именно - Вам тоже надо доползти до Европы. Единственно, Вы избавились от идентификатора, который я ввел искусственно. Это несомненно плюс.
Я вот Вам чего предлагаю - Вы вот то что все мне предлагаете попробуйте пошагово выполнить сами. Операция же проста - переместить Москву из Европы в Австралию. Просто чтобы понять проблему изнутри, я может просто объяснить не могу правильно.
Вот как Вы будете перемещать Москву?
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика

Последний раз редактировалось Utkin; 21.06.2016 в 12:55.
Utkin вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как избавиться от запроса доступа к внешним данным Loshara Microsoft Office Excel 0 29.07.2015 14:13
Страницы доступа к данным Jimmy Lenox Microsoft Office Access 0 19.10.2012 15:12
страницы доступа к данным... AGhost Microsoft Office Access 3 21.05.2010 23:05
Создание класс с использованием методов доступа к данным El_Bint0 Помощь студентам 1 14.03.2007 10:16