imho.ws
IMHO.WS  

Вернуться   IMHO.WS > Веб-мастеру > Веб-программирование
Опции темы
Старый 19.03.2005, 23:51     # 41
Sheryld
Full Member
 
Регистрация: 29.05.2002
Сообщения: 544

Sheryld Луч света в тёмном царствеSheryld Луч света в тёмном царствеSheryld Луч света в тёмном царствеSheryld Луч света в тёмном царствеSheryld Луч света в тёмном царстве
сортировка по нескольким полям(с данными) одновременно врядли может понадобиться...
__________________
убрано по просьбе администратора
Sheryld вне форума  
Старый 21.03.2005, 11:10     # 42
Sheryld
Full Member
 
Регистрация: 29.05.2002
Сообщения: 544

Sheryld Луч света в тёмном царствеSheryld Луч света в тёмном царствеSheryld Луч света в тёмном царствеSheryld Луч света в тёмном царствеSheryld Луч света в тёмном царстве
метод для обмена двух узлов:
Код:
function SwapNodes($categoryID1, $categoryID2)
		{
			if ($this->getNodeInfo($categoryID1) == 0)
			{
				$nodeInfo1 = $this->nodeInfo;
			}
			if ($this->getNodeInfo($categoryID2) == 0)
			{
				$nodeInfo2 = $this->nodeInfo;
			}
			// todo:
			// check for rule: both nodes must have same parentID
			$db = new MySql(null, "mport4", null, null);
			$db->MySql_Connect();
			$db->MySql_SelectDb();
			
			$updateQuery = "update categories set
			cat_LEFT = case 
			when cat_LEFT between " . $nodeInfo1["left"] . " and " . $nodeInfo1["right"] . " then " . 
			$nodeInfo2["right"] . "+cat_LEFT-" . $nodeInfo1["right"] .
			" when cat_LEFT between " . $nodeInfo2["left"] . " and " . $nodeInfo2["right"] . " then "  .
			$nodeInfo1["left"] . "+cat_LEFT-" . $nodeInfo2["left"] . " else " .
			$nodeInfo1["left"] . "+" .  $nodeInfo2["right"] . "+cat_LEFT-" . $nodeInfo1["right"] . "-" . $nodeInfo2["left"] . " end," .
			" cat_RIGHT = case
			when cat_RIGHT between " . $nodeInfo1["left"] . " and " .  $nodeInfo1["right"] . " then " .
			$nodeInfo2["right"]  . "+cat_RIGHT-" . $nodeInfo1["right"] .
			" when cat_RIGHT between " . $nodeInfo2["left"] . " and " . $nodeInfo2["right"] . " then " .
			$nodeInfo1["left"] . "+cat_RIGHT-" . $nodeInfo2["left"] . " else " .
			$nodeInfo1["left"] . "+" . $nodeInfo2["right"] . "+cat_RIGHT-" . $nodeInfo1["right"] . "-" . $nodeInfo2["left"] . " end " .
			" where cat_LEFT between " . $nodeInfo1["left"] . " and " . $nodeInfo2["right"] . 
			" and " . $nodeInfo1["left"] . "<" . $nodeInfo1["right"] . 
			" and " . $nodeInfo1["right"] . "<" . $nodeInfo2["left"] .
			" and " . $nodeInfo2["left"] . "<" . $nodeInfo2["right"];
			
			$db->MySql_QueryDb($updateQuery);
			
			if (mysql_affected_rows($db->dbConn) > 0)
			{
				return 0;				
			}
			return -1;			
		}
p.s. нужно добавить проверки.
__________________
убрано по просьбе администратора
Sheryld вне форума  
Старый 21.03.2005, 19:21     # 43
is_absent
::VIP::
 
Аватар для is_absent
 
Регистрация: 27.01.2004
Адрес: Россия. Барнаул
Пол: Male
Сообщения: 417

is_absent Молодецis_absent Молодецis_absent Молодец
Когда будешь вводить внешний индекс сортировки, его нужно строить так, чтобы сохранялась структура дерева. То есть помимо простой сортировки нужно будет учитывать и сортировку по left. Это влечет как минимум дополнительные вычисления. А в общем идея здравая.

Цитата:
Sheryld:
if ($this->getNodeInfo($categoryID1) == 0)
{
$nodeInfo1 = $this->nodeInfo;
}
подобные конструкции не всегда удобны... это уже к делу не отностится, но на мой взгляд метод, начинающийся с "get", должен возвращать запрашиваемое значение, а не устанавливать внутреннее свойство класса.
Для проверки удачного/неудачного чтения данных достаточно возавращать false в последнем случае и тогда не совсем верная конструкция (процитированная) превратится в немного более сложную
Код:
if (false === ($nodeInfo1 = $this->getNodeInfo($categoryID1)) return false;
но обеспечивающую достаточную защиту от некорретных данных
__________________
Nunc est bibendum
is_absent вне форума  
Старый 21.03.2005, 19:59     # 44
Sheryld
Full Member
 
Регистрация: 29.05.2002
Сообщения: 544

Sheryld Луч света в тёмном царствеSheryld Луч света в тёмном царствеSheryld Луч света в тёмном царствеSheryld Луч света в тёмном царствеSheryld Луч света в тёмном царстве
тут бы вообще надо создавать новый экземпляр класса, с копирующим конструктором, но я не знаю, как это сделать в php.
__________________
убрано по просьбе администратора
Sheryld вне форума  
Старый 21.03.2005, 20:51     # 45
is_absent
::VIP::
 
Аватар для is_absent
 
Регистрация: 27.01.2004
Адрес: Россия. Барнаул
Пол: Male
Сообщения: 417

is_absent Молодецis_absent Молодецis_absent Молодец
Цитата:
Sheryld:
тут бы вообще надо создавать новый экземпляр класса, с копирующим конструктором, но я не знаю, как это сделать в php.
В четверке почти никак, только ручками создавать копию, либо определять собственный метод clone(). В пятом есть магический метод __clone()...
__________________
Nunc est bibendum
is_absent вне форума  
Старый 21.03.2005, 22:25     # 46
Sheryld
Full Member
 
Регистрация: 29.05.2002
Сообщения: 544

Sheryld Луч света в тёмном царствеSheryld Луч света в тёмном царствеSheryld Луч света в тёмном царствеSheryld Луч света в тёмном царствеSheryld Луч света в тёмном царстве
подводя итоги. не хватает методов:

InsertTo
MoveTo

т.е. вставлять/двигать узел(целиком) в конкретную позицию.

Clone

клонировать узел.

Одиночное удаление узла. Но это вобщем не сложно и не к спеху

если кто знает где найти алгоритмы, прошу ссылку
__________________
убрано по просьбе администратора
Sheryld вне форума  
Старый 22.03.2005, 14:34     # 47
is_absent
::VIP::
 
Аватар для is_absent
 
Регистрация: 27.01.2004
Адрес: Россия. Барнаул
Пол: Male
Сообщения: 417

is_absent Молодецis_absent Молодецis_absent Молодец
InsetTo и Clone по сути одно и то же если речь идет о копировании существующего узла.
Решать можно так:
1. Выбираем поддерево с корнем в нужном нам узле.
2. Вызываем рекурсивный метод добавления дерева в дерево (пишется за 10 минут)

С переносом сложнее.. там нужно сохранить и идентификаторы, но как вариант, можно сначала скопировать куда-нибудь в переменную поддерево, которое переносим, удалить его и вставить в нужное место с указанием всех данных (кроме left, right и level)

Sheryld
Цитата:
Sheryld:
Одиночное удаление узла
а вот это не так легко.. тебе надо что-то сделать с детями узла
__________________
Nunc est bibendum
is_absent вне форума  
Старый 22.03.2005, 14:50     # 48
Sheryld
Full Member
 
Регистрация: 29.05.2002
Сообщения: 544

Sheryld Луч света в тёмном царствеSheryld Луч света в тёмном царствеSheryld Луч света в тёмном царствеSheryld Луч света в тёмном царствеSheryld Луч света в тёмном царстве
нет. я хочу одним запросом, чтобы было в том же стиле, что и все остальные запросы в выходные устроим очередной мозговой штурм

и кстати, насчет рекурсивного метода не понял. к чему он тут?
__________________
убрано по просьбе администратора
Sheryld вне форума  
Старый 22.03.2005, 20:32     # 49
is_absent
::VIP::
 
Аватар для is_absent
 
Регистрация: 27.01.2004
Адрес: Россия. Барнаул
Пол: Male
Сообщения: 417

is_absent Молодецis_absent Молодецis_absent Молодец
рекурсивный метод -- самый простой способ решить эту задачу. не всегда правда оптимальный.

Теперь давай смотреть на структуру дерева.
При добавлении N узлов нужно увеличить left и right всех узлов "правее" нового на 2*N. При удалении этих же N узлов -- на 2*N.

Теперь дальше. При изменении родителя узла нужно изменить left, right и level. С последним все ясно. с left и right дело обстоит так:
новый left (и right) узлов, который перенесли и всех узлов "правее" нужно увеличить на разность right родителя и left исходного.

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

Выглядит это так
1. Сдвигаю дерево для новых узлов
2. Меняю left и right указанного узла и его детей так, чтобы они заполнили пустое место.
3. Ещё раз сдвигаю дерево.

Если оптимизировать до одного запроса, то нужно ставить в запрос условия на left и right.
выделять нужно три варианта:
1. узел между тем, в который вставляют и тем который вставляют.
2. узел внутри того, который вставляют.
3. узел после того, который вставляют.

Первую группу сдвигаем "вправо" на количество вставляемых узлов.
Для второй группы изменяем родителя.
Третью сдвигаем "влево" на количество вставляемых узлов + изменяем level этих узлов.

Направления "вправо" и "влево" чисто условные. Определить их можно так:
Если вставляемый узел выше (в таблице отсортированной по left) того, в который вставляют, то "вправо" - это увеличение индексов, "влево" - уменьшение. В противном случае -- наоборот

Кажется так. И относится это только к переносу. Для копирования я так и не придумал ничего лучше рекурсивного перебора всех узлов, которые нужно скопировать.
__________________
Nunc est bibendum
is_absent вне форума  


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

BB код Вкл.
Смайлы Вкл.
[IMG] код Выкл.
HTML код Выкл.

Быстрый переход


Часовой пояс GMT +4, время: 13:50.




Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.