То, как Вы сортируете дерево, сохранило использование вложенной модели набора?

Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int:

int x;
x = 10;

В этом примере переменная x является int, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.

Но когда вы пытаетесь объявить ссылочный тип, произойдет что-то другое. Возьмите следующий код:

Integer num;
num = new Integer(10);

Первая строка объявляет переменную с именем num, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».

Во второй строке ключевое слово new используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования . (точка).

Exception, о котором вы просили, возникает, когда вы объявляете переменную, но не создавали объект. Если вы попытаетесь разыменовать num. Перед созданием объекта вы получите NullPointerException. В самых тривиальных случаях компилятор поймает проблему и сообщит вам, что «num не может быть инициализирован», но иногда вы пишете код, который непосредственно не создает объект.

Например, вы можете имеют следующий метод:

public void doSomething(SomeObject obj) {
   //do something to obj
}

В этом случае вы не создаете объект obj, скорее предполагая, что он был создан до вызова метода doSomething. К сожалению, этот метод можно вызвать следующим образом:

doSomething(null);

В этом случае obj имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.

Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething может быть записано как:

/**
  * @param obj An optional foo for ____. May be null, in which case 
  *  the result will be ____.
  */
public void doSomething(SomeObject obj) {
    if(obj != null) {
       //do something
    } else {
       //do something else
    }
}

Наконец, Как определить исключение & amp; причина использования Трассировки стека

16
задан Taryn 16 July 2013 в 01:40
поделиться

5 ответов

Я использовал Вложенные Наборы много, и я часто сталкивался с той же проблемой. То, что я делаю, и что я рекомендовал бы, не должно просто сортировать объекты в базе данных. Вместо этого отсортируйте их в пользовательском интерфейсе. После получения по запросу всех узлов от DB, вероятно, необходимо преобразовать их в некоторую иерархическую структуру данных, так или иначе. В той структуре, вид все массивы, содержащие детей узла.

, Например, если Ваш frontend является приложением Flex и детьми узла, хранятся в ICollectionView, можно использовать свойство вида, чтобы сделать, чтобы они отобразили способ, которым Вы хотите.

Другой пример, если Ваш frontend является некоторым выводом из Сценария PHP, Вы могли бы иметь детей каждого узла в массиве и использовать функции сортировки массива PHP для выполнения сортировки.

, Конечно, это только работает, если Вы не нуждаетесь в фактических записях дб, которые будут отсортированы, но делаете Вас?

4
ответ дан 30 November 2019 в 23:14
поделиться

Я только что закончил писать следующее, которое работает на меня в сортировке всего вложенного дерева набора.

вид (идеально) требует представления, которое перечисляет текущий уровень каждого узла в дереве и процедуре свопинга двух узлов - оба включены ниже, одноуровневый код подкачки появляется от Joe Celkos 'Дерево & книга Иерархий, которую я настоятельно рекомендую любому использующему вложенные наборы.

вид может быть изменен в операторе 'INSERT INTO @t', здесь это - простой алфавитно-цифровой вид на 'Имени'

, Это может быть плохим способом сделать его особенно использование курсора для основанного на наборе кода, но поскольку я говорю, что он работает на меня, надежда, которой он помогает.

ОБНОВЛЕНИЕ:

Код ниже теперь показывает версию, не используя курсор. Я занимаюсь 10x улучшения скорости

CREATE VIEW dbo.tree_view

AS

SELECT t2.NodeID,t2.lft,t2.rgt ,t2.Name, COUNT(t1.NodeID) AS level  
FROM dbo.tree t1,dbo.tree t2
WHERE t2.lft BETWEEN t1.lft AND t1.rgt
GROUP BY t2.NodeID,t2.lft,t2.rgt,t2.Name

GO

----------------------------------------------

  DECLARE @CurrentNodeID int
DECLARE @CurrentActualOrder int
DECLARE @CurrentRequiredOrder int
DECLARE @DestinationNodeID int
DECLARE @i0 int
DECLARE @i1 int
DECLARE @i2 int
DECLARE @i3 int

DECLARE @t TABLE (TopLft int,NodeID int NOT NULL,lft int NOT NULL,rgt int NOT NULL,Name varchar(50),RequiredOrder int NOT NULL,ActualOrder int NOT NULL)


INSERT INTO @t (toplft,NodeID,lft,rgt,Name,RequiredOrder,ActualOrder)
    SELECT tv2.lft,tv1.NodeID,tv1.lft,tv1.rgt,tv1.Name,ROW_NUMBER() OVER(PARTITION BY tv2.lft ORDER BY tv1.ColumnToSort),ROW_NUMBER() OVER(PARTITION BY tv2.lft ORDER BY tv1.lft ASC)
    FROM dbo.tree_view tv1 
    LEFT OUTER JOIN dbo.tree_view tv2 ON tv1.lft > tv2.lft and tv1.lft < tv2.rgt and tv1.level = tv2.level+1
    WHERE tv2.rgt > tv2.lft+1

    DELETE FROM @t where ActualOrder = RequiredOrder


WHILE EXISTS(SELECT * FROM @t WHERE ActualOrder <> RequiredOrder)
BEGIN


    SELECT Top 1 @CurrentNodeID = NodeID,@CurrentActualOrder = ActualOrder,@CurrentRequiredOrder = RequiredOrder
    FROM @t 
    WHERE ActualOrder <> RequiredOrder
    ORDER BY toplft,requiredorder

    SELECT @DestinationNodeID = NodeID
    FROM @t WHERE ActualOrder = @CurrentRequiredOrder AND TopLft = (SELECT TopLft FROM @t WHERE NodeID = @CurrentNodeID) 

    SELECT @i0 = CASE WHEN c.lft < d.lft THEN c.lft ELSE d.lft END,
            @i1 =  CASE WHEN c.lft < d.lft THEN c.rgt ELSE d.rgt END,
            @i2 =  CASE WHEN c.lft < d.lft THEN d.lft ELSE c.lft END,
            @i3 =  CASE WHEN c.lft < d.lft THEN d.rgt ELSE c.rgt END
    FROM dbo.tree c
    CROSS JOIN dbo.tree d
    WHERE c.NodeID = @CurrentNodeID AND d.NodeID = @DestinationNodeID

    UPDATE dbo.tree
    SET lft = CASE  WHEN lft BETWEEN @i0 AND @i1 THEN @i3 + lft - @i1
                    WHEN lft BETWEEN @i2 AND @i3 THEN @i0 + lft - @i2
            ELSE @i0 + @i3 + lft - @i1 - @i2
            END,
        rgt = CASE  WHEN rgt BETWEEN @i0 AND @i1 THEN @i3 + rgt - @i1
                    WHEN rgt BETWEEN @i2 AND @i3 THEN @i0 + rgt - @i2
            ELSE @i0 + @i3 + rgt - @i1 - @i2
            END
    WHERE lft BETWEEN @i0 AND @i3 
    AND @i0 < @i1
    AND @i1 < @i2
    AND @i2 < @i3

    UPDATE @t SET actualorder = @CurrentRequiredOrder where NodeID = @CurrentNodeID
    UPDATE @t SET actualorder = @CurrentActualOrder where NodeID = @DestinationNodeID

    DELETE FROM @t where ActualOrder = RequiredOrder

END
2
ответ дан 30 November 2019 в 23:14
поделиться

Да это - ограничение вложенной модели набора, так как вложенные наборы являются предварительно заказанным представлением иерархии. Это делать предзаказ является причиной, что это настолько быстро для чтений. Модель смежности, также описанная на странице, с которой Вы связываетесь, предусматривает самую гибкую сортировку и фильтрацию, но со значительным влиянием производительности.

Мой предпочтительный подход для вставок и перемещения во вложенном наборе должны обработать затронутое ответвление как в модели смежности: Получите список новых одноуровневых элементов; найдите правильное место в списке для нового узла; и создайте необходимые операторы обновления (что, будучи битом, где действительно необходимо быть осторожными). Что касается изменения Ваших критериев упорядочивания: это - то от пакетного задания, таким образом, можно позволить себе унести некоторую RAM и ЦП на ней, самый гибкий ответ должен был бы разломать вложенное представление набора на представление смежности и восстановить вложенный набор от смежности на основе новых критериев.

1
ответ дан 30 November 2019 в 23:14
поделиться

Я думаю, что это - действительно ограничение вложенной модели набора. Вы не можете легко отсортировать дочерние узлы в их соответствующем родительском узле, потому что упорядочивание набора результатов важно для восстановления древовидной структуры.

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

можно также инвертировать порядок сортировки предварительно отсортированного дерева. Просто необходимо использовать ORDER BY node.rgt DESC вместо ORDER BY node.lft ASC.

, Если действительно необходимо поддерживать другого критерии сортировки, Вы могли возможная реализация это путем добавления секунды lft и rgt индекс к каждому узлу и сохранять отсортированным по другим критериям на каждом вставляемые/обновлять/удалять.

4
ответ дан 30 November 2019 в 23:14
поделиться

Я считаю, что в вашем случае, когда узлы, которые вы хотите поменять местами, не имеют потомков, вы можете просто поменять местами значения lft и rgt. Рассмотрим это дерево:

   A
 /   \
B     C
     / \
    D   E

Это может превратиться в эту группу вложенных наборов:

1 A 10 
2 B 3  
4 C 9
5 D 6
7 E 8

Теперь представьте, что вы хотите поменять местами D и E. Следующие вложенные наборы действительны, и D и E поменяны местами:

1 A 10
2 B 3 
4 C 9 
7 D 8
5 E 6 

Обмен узлов, которые имеют поддеревья, конечно, не могут быть выполнены таким образом, потому что вам также нужно будет обновить дочерние значения lft и rgt.

0
ответ дан 30 November 2019 в 23:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: