За последние 24 часа нас посетили 22723 программиста и 1259 роботов. Сейчас ищут 696 программистов ...

Новичкам: Организация древовидной структуры

Тема в разделе "Решения, алгоритмы", создана пользователем Vitas, 11 июн 2007.

  1. Vitas

    Vitas Активный пользователь

    С нами с:
    7 фев 2006
    Сообщения:
    595
    Симпатии:
    0
    Адрес:
    Новосибирск, Академгородок
    Частенько возникает необходимость организовать что-либо в виде дерева, например форум.

    Первое, что приходит в голову, это создать таблицу с примерно такой структурой:
    Код (Text):
    1. id - номер сообщения
    2. parent_id - номер сообщения родителя (0, если сообщение начало темы)
    3. body - собственно, сообщение
    Но чтобы вывести такой форум придется использовать рекурсию, что очень дурно повлияет на производительность скрипта.

    Поэтому, у меня появилась идея: использовать специальное поле для сортировки строк. Итак, подробнее.
    Сначала создадим таблицу 'msgs' такого содержания:
    Код (Text):
    1. body - само сообщение
    2. orderby - то самое специальное поле
    Итак, в этом поле будут храниться даты сообщений в формате:
    Код (Text):
    1. дата сообщения, которое является началом темы / дата ответа на это предыдущее сообщение / дата ответа на это предыдущее сообщение ...
    Если пользователь начинает новую тему например 1 января 2007 года в 00:00, то это поле имеет такой вид:
    Код (Text):
    1. 2007-01-01 00:00
    Позже пришел еще какой-то пользователь и решил написать свое сообщение (в час ночи), тогда поле имеет такой вид:
    Код (Text):
    1. 2007-01-01 00:00/2007-01-01 01:00
    И так далее, по нарастающей.

    Теперь чтобы выбрать нужные строки и в нужном порядке то надо будет использовать всего 1 запрос, не используя рекурсию:
    [sql]SELECT * FROM msgs ORDER BY orderby ASC[/sql]

    Все стало намного прозрачнее, НО есть один минус длина поля будет постоянно расти, поэтому придется позаботится о том, чтобы длина поля была достаточной или использовать другой формат записи например не использовать дату а unix timestamp.
     
  2. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    это у тебя будет тормозить на ровном месте...
     
  3. Vitas

    Vitas Активный пользователь

    С нами с:
    7 фев 2006
    Сообщения:
    595
    Симпатии:
    0
    Адрес:
    Новосибирск, Академгородок
    Угу-с. :)
     
  4. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    Vitas
    Можно вопрос: а почему у тебя форум получился в виде дерева?
    Все современные профессиональные движки (SMF, vB, IPB, phpBB) - не древовидные, а нитевидные. Наверное, неспроста их создатели так решили.
    Древовидной может быть структура разделов, но не сообщения. Иначе форум быстро превратится в помойку, в которой фиг чего найдешь (имхо).
     
  5. Amian

    Amian Активный пользователь

    С нами с:
    15 мар 2007
    Сообщения:
    189
    Симпатии:
    0
    Алгоритмы сортировки занимают больше времени,чем выборка необходимых элементов при правильном построении дерева.Думаю что самый быстрый вариант для реализации этой мысли будет использовать какое-нибудь self-balancing heap-ообразное дерево и выводить затем данные "in level-order".Т.е. сортировка будет производиться лишь 1 раз при добавлении новых постов/ответов,а не каждый раз,как в приведённом тобой примере.Значения элементов = время поста + дополнительные указатели в каждом из элементов на остальную инфу. Для каждого поста новое дерево,каждый элемент которого будет ссылаться на поддерево "ответов к посту".Правда писать такое думаю придёться на С,если нет уже готовых реализаций в существующих базах данных :p
     
  6. Vitas

    Vitas Активный пользователь

    С нами с:
    7 фев 2006
    Сообщения:
    595
    Симпатии:
    0
    Адрес:
    Новосибирск, Академгородок
    Это значит не обязательно форум, может быть какой-нить каталог.
     
  7. Vitas

    Vitas Активный пользователь

    С нами с:
    7 фев 2006
    Сообщения:
    595
    Симпатии:
    0
    Адрес:
    Новосибирск, Академгородок
    Amian
    Спасибо за информацию. ;)
     
  8. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    Vitas
    Хм... в таком случае тебя понесло не в ту степь, имхо. Если ты вместо форума будешь рассматривать другую предметную область, то у тебя все изменится - исчезнет понятие "последнего сообщения" (а ведь у тебя на нем все рассуждение построено), появятся другие поля и задачи. Думаю, для каждой области требуется свое решение и своя структура для хранения данных, универсальности здесь лучше не искать.
     
  9. Vitas

    Vitas Активный пользователь

    С нами с:
    7 фев 2006
    Сообщения:
    595
    Симпатии:
    0
    Адрес:
    Новосибирск, Академгородок
    Почему же? Если мы будем делать каталог, то все папки можно будет привести к виду
    "/папка1/папка2 и т.д.", все то же самое.
     
  10. Davil

    Davil Guest

  11. Vitas

    Vitas Активный пользователь

    С нами с:
    7 фев 2006
    Сообщения:
    595
    Симпатии:
    0
    Адрес:
    Новосибирск, Академгородок
    Давно курил и просветлился, правда реализовать такой алгоритм руки не доходили.

    А тему закройте, алгоритм неудачный.
     
  12. Vitas

    Vitas Активный пользователь

    С нами с:
    7 фев 2006
    Сообщения:
    595
    Симпатии:
    0
    Адрес:
    Новосибирск, Академгородок
    Кстати, а если в таблицу добавить столбец, например, sort, по которому будут сортироваться строки во время выборки:
    [sql]SELECT * FROM tree ORDER BY sort[/sql]
    А во время изменения дерева использовать такой запрос:
    [sql]SET @i = 0;
    UPDATE tree SET sort = (@i := @i + 1) ORDER BY orderby[/sql]
    Будет ли это целесообразно?
     
  13. antonn

    antonn Активный пользователь

    С нами с:
    10 июн 2007
    Сообщения:
    2.996
    Симпатии:
    0
    ИПБ не нитевидный. В нем есть кнопочка "Ответить" и быстрый ответ, и что то там "Цитата". При ответе парентом становится последнее сообщение, при цитате - парентом становится пост. при нитевидной организации посты выводятся по времени поста, при дереве - выводятся деревом.