2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




На страницу 1, 2, 3  След.
 
 Двоичное дерево поиска
Сообщение11.08.2017, 13:48 
Пожалуйста, помогите понять следующий код:
код: [ скачать ] [ спрятать ]
Используется синтаксис Python
class Tree:
 
    def __init__(self, value, root=None):
        self.lchild = None
        self.rchild = None
        self.value = value
        self.root = root
 
    def add(self, value):
        current_node = self
        last_node = None
        while current_node:
            last_node = current_node
 
            if value > current_node.value:
               current_node = current_node.rchild
            elif value < current_node.value:
                 current_node = current_node.lchild
            else:
                return False
     new_node = Tree(value, last_node)
        if value > last_node.value:
           last_node.rchild = new_node
        else:
            last_node.lchild = new_node
            return True

Спасибо!

 
 
 
 Re: Двоичное дерево поиска
Сообщение11.08.2017, 13:50 
Аватара пользователя
А что именно Вы в этом коде не понимаете?

 
 
 
 Re: Двоичное дерево поиска
Сообщение11.08.2017, 13:52 
Конкретно:
kotenok gav в сообщении #1239959 писал(а):
root=None

kotenok gav в сообщении #1239959 писал(а):
current_node = self
last_node = None

kotenok gav в сообщении #1239959 писал(а):
while current_node:

 
 
 
 Re: Двоичное дерево поиска
Сообщение11.08.2017, 14:36 
Аватара пользователя
А где Вы этот код взяли? Неужели никаких пояснений нет?

Насколько я понял, root - это указание родителя вершины. По умолчанию мы создаем новое дерево, и root ставим None - новое дерево ни к чему не привязано. А вот например в строке new_node = Tree(value, last_node) мы создаем новую вершину в существующем дереве.

current_node и last_node - что Вам непонятно? мы идем по дереву, храня текущее место и предыдущее. В начале current_node - это вершина, для которой вызвали add, т.е. self, а last_node ненужна, поэтому мы устанавливаем ее в None
Вообще, две переменные не обязательны, можно использовать только одну, разберитесь сами, как.

while current_node: - это использует то, что в питоне None - это ложное значение, а определенные пользователем объекты - истинные, если не сказано иначе. Чтобы было понятнее, можно переписать как while current_node is not None:

 
 
 
 Re: Двоичное дерево поиска
Сообщение11.08.2017, 14:43 
Спасибо!
Кстати, а что такое "elif"?

 
 
 
 Re: Двоичное дерево поиска
Сообщение11.08.2017, 14:46 
kotenok gav в сообщении #1239994 писал(а):
Кстати, а что такое "elif"?
"Сокращение" от else if.

 
 
 
 Re: Двоичное дерево поиска
Сообщение14.08.2017, 19:27 
Аватара пользователя
Xaositect в сообщении #1239993 писал(а):
Вообще, две переменные не обязательны, можно использовать только одну, разберитесь сами, как.

Вы не представляете, как это выглядит со стороны. :lol: «Объясните, пожалуйста». — «Разбирайтесь сами».

-- Mon Aug 14, 2017 19:47:25 --

Мне тоже было трудно понять код. На функциональном япе он выглядит элегантнее, потому что там разделены изменяемые и неизменяемые типы данных. Вообще императивность не добавляет ясности. Для сравнения привожу код на Standard ML:
Используется синтаксис OCaml
datatype 'a tree_set = tip |
         node of {value : 'a,
                  left : 'a tree_set ref, right : 'a tree_set ref};
fun add a =
  let fun loop t =
        case ! t of
            tip => (t := node {value = a,
                               left = ref tip, right = ref tip};
                    true)
          | node n => if a < #value n then loop (#left n)
                      else if a > #value n then loop (#right n)
                      else false
  in loop end

В узле дерева лежат не просто поддеревья, а ячейки («ref»), содержащие поддеревья. Содержимое ячеек менять можно, компоненты узла дерева менять нельзя. Функция «add» находит ячейку, которая должна содержать «a». Если эта ячейка содержит «tip» (аналогичен «None» в Python), тогда заменяем её содержимое на новый узел, содержащий «a». В Python метод «add» находит некий «last_node». Так вот, та ячейка, которую находит функция «add» в Standard ML, соответствует правому или левому компоненту «last_node». Какому именно компоненту, определяется последним «if». Этот «if» лишний с точки зрения Standard ML.

В Standard ML можно манипулировать ячейкой. Аналогичный код можно написать на C, в качестве ячейки будет указатель на компонент узла дерева. В Python так сделать нельзя, потому что в Python сборка мусора автоматическая, и для сборщика мусора нужно, чтобы каждый указатель указывал на целый объект кучи, а не на его компоненты.

 
 
 
 Re: Двоичное дерево поиска
Сообщение15.08.2017, 11:39 
Xaositect в сообщении #1239993 писал(а):
while current_node: - это использует то, что в питоне None - это ложное значение, а определенные пользователем объекты - истинные, если не сказано иначе. Чтобы было понятнее, можно переписать как while current_node is not None:

А бесконечного цикла, случайно, не получится? А то во время while, current_node разве когда-нибудь станет None?

 
 
 
 Re: Двоичное дерево поиска
Сообщение15.08.2017, 11:43 
Аватара пользователя
Дерево-то у нас конечное, рано или поздно доберёмся до листьев.

 
 
 
 Re: Двоичное дерево поиска
Сообщение15.08.2017, 12:02 
А почему в листьях current_node будет None?

 
 
 
 Re: Двоичное дерево поиска
Сообщение15.08.2017, 12:10 
Аватара пользователя
Потому что не будет соответствующих lchild И rchild, насколько я понимаю код.

 
 
 
 Re: Двоичное дерево поиска
Сообщение15.08.2017, 12:19 
Я сейчас немного модифицировал этот код, чтобы он осуществлял сортировку бинарным деревом. Он будет работать?
код: [ скачать ] [ спрятать ]
Используется синтаксис Python
class Tree:
    def _init_(self, value, root = None):
        self.lchild = None
        self.rchild = None
        self.value = value
        self.root = root
    def add(self, value):
        current_node = self
        last_node = None
        while current_node:
            last_node = current_node
            if value < current_node.value:
                current_node = current_node.lchild
            else:
                current_node = current_node.rchild
        new_node = Tree(value, last_node)
        if value > last_node.value:
            last_node.rchild = new_node
        else:
            last_node.rchild = new_node
    def write(self):
        if self.lchild == None:
            if self.rchild == None:
                return self.value
            else:
                return self.value + self.write(self.rchild)
        else:
            if self.rchild == None:
                return self.write(self.lchild) + self.value
            else:
                return self.write(self.lchild) + self.value + self.write(self.rchild)
print('Insert number of numbers')
n = int(input())
print('Insert 1-st number')
a1 = float(input())
root = Tree(a1)
for i in range(2, n + 1):
    a = float(input())
    root.add(a)
root.write()

 
 
 
 Re: Двоичное дерево поиска
Сообщение15.08.2017, 12:35 
Аватара пользователя
А вы проверьте ;-)

(Спойлер)

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

 
 
 
 Re: Двоичное дерево поиска
Сообщение15.08.2017, 12:49 
Eclipse сказал, что в строчке "root = Tree(a1)" нет аргументов.
Но a1 - аргумент, ведь так?
Тогда почему код выдает ошибку?

 
 
 
 Re: Двоичное дерево поиска
Сообщение15.08.2017, 12:59 
Аватара пользователя
Нашёл очень смешную ошибку. Вы откуда код копировали-то? В определении класса у вас _init_ там, где должно быть __init__.

 
 
 [ Сообщений: 31 ]  На страницу 1, 2, 3  След.


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group