Jak implementovat binární vyhledávací strom v Pythonu?

hlasů
25

To je to, co jsem se dostal tak daleko, ale to nefunguje:

class Node:
    rChild,lChild,data = None,None,None

    def __init__(self,key):
        self.rChild = None
        self.lChild = None
        self.data = key

class Tree:
    root,size = None,0
    def __init__(self):
        self.root = None
        self.size = 0

    def insert(self,node,someNumber):
        if node is None:
            node = Node(someNumber)
        else:
            if node.data > someNumber:
                self.insert(node.rchild,someNumber)
            else:
                self.insert(node.rchild, someNumber)
        return

def main():
    t = Tree()
    t.root = Node(4)
    t.root.rchild = Node(5)
    print t.root.data #this works
    print t.root.rchild.data #this works too
    t = Tree()
    t.insert(t.root,4)
    t.insert(t.root,5)
    print t.root.data #this fails
    print t.root.rchild.data #this fails too

if __name__ == '__main__':
     main()
Položena 26/03/2011 v 19:37
zdroj uživatelem
V jiných jazycích...                            


17 odpovědí

hlasů
5

OP je Tree.insertmetoda kvalifikuje pro „Gross nesprávné pojmenování v týdnu“ cena - to není nic vložit. To vytvoří uzel, který není připojen na jiný uzel (ne, že jsou všechny uzly na něj se připojit) a pak se vytvořený uzel je ničeny, pokud metoda vrátí.

Pro povznesení @Hugh Bothwell:

>>> class Foo(object):
...    bar = None
...
>>> a = Foo()
>>> b = Foo()
>>> a.bar
>>> a.bar = 42
>>> b.bar
>>> b.bar = 666
>>> a.bar
42
>>> b.bar
666
>>>
Odpovězeno 26/03/2011 v 19:50
zdroj uživatelem

hlasů
9
class Node: 
    rChild,lChild,data = None,None,None

To je v pořádku - to je vaše proměnné proměnné třídy - to znamená, že každý případ uzlu používá stejné hodnoty (změna rChild některého uzlu jej změní pro všechny uzly!). To zjevně není to, co chcete; Snaž se

class Node: 
    def __init__(self, key):
        self.rChild = None
        self.lChild = None
        self.data = key

Nyní každý uzel má svou vlastní sadu proměnných. Totéž platí pro vaše definice Tree,

class Tree:
    root,size = None,0    # <- lose this line!
    def __init__(self):
        self.root = None
        self.size = 0

Dále, každá třída by měla být „nový styl“ třídy odvozené od třídy „objekt“ a měl by řetězec zpět do objektu .__ init __ ():

class Node(object): 
    def __init__(self, data, rChild=None, lChild=None):
        super(Node,self).__init__()
        self.data   = data
        self.rChild = rChild
        self.lChild = lChild

class Tree(object):
    def __init__(self):
        super(Tree,self).__init__()
        self.root = None
        self.size = 0

Také main () je členité příliš daleko - jak je vidět, že je to způsob stromu, který je uncallable protože nepřijímá vlastní argument.

Také měníte data objektu přímo ( t.root = Node(4)), který druh zničí zapouzdření (celý bod s tříd v první řadě); byste měli dělat něco více jako

def main():
    t = Tree()
    t.add(4)    # <- let the tree create a data Node and insert it
    t.add(5)
Odpovězeno 26/03/2011 v 20:01
zdroj uživatelem

hlasů
1

Prostě něco, který vám pomůže začít.

A (jednoduchá myšlenka) binární vyhledávací stromy by bylo docela pravděpodobné, že bude realizovat v pythonu podle řádky:

def search(node, key):
    if node is None: return None  # key not found
    if key< node.key: return search(node.left, key)
    elif key> node.key: return search(node.right, key)
    else: return node.value  # found key

Nyní stačí provést lešení (vytvoření stromu a hodnotu vložky) a je hotovo.

Odpovězeno 26/03/2011 v 20:12
zdroj uživatelem

hlasů
45

Zde je rychlý příklad binární vložky:

class Node:
    def __init__(self, val):
        self.l_child = None
        self.r_child = None
        self.data = val

def binary_insert(root, node):
    if root is None:
        root = node
    else:
        if root.data > node.data:
            if root.l_child is None:
                root.l_child = node
            else:
                binary_insert(root.l_child, node)
        else:
            if root.r_child is None:
                root.r_child = node
            else:
                binary_insert(root.r_child, node)

def in_order_print(root):
    if not root:
        return
    in_order_print(root.l_child)
    print root.data
    in_order_print(root.r_child)

def pre_order_print(root):
    if not root:
        return        
    print root.data
    pre_order_print(root.l_child)
    pre_order_print(root.r_child)    

r = Node(3)
binary_insert(r, Node(7))
binary_insert(r, Node(1))
binary_insert(r, Node(5))

     3
    / \
   1   7
      /
     5

print "in order:"
in_order_print(r)

print "pre order"
pre_order_print(r)

in order:
1
3
5
7
pre order
3
1
7
5
Odpovězeno 26/03/2011 v 20:35
zdroj uživatelem

hlasů
5
class Node:
    rChild,lChild,parent,data = None,None,None,0    

def __init__(self,key):
    self.rChild = None
    self.lChild = None
    self.parent = None
    self.data = key 

class Tree:
    root,size = None,0
    def __init__(self):
        self.root = None
        self.size = 0
    def insert(self,someNumber):
        self.size = self.size+1
        if self.root is None:
            self.root = Node(someNumber)
        else:
            self.insertWithNode(self.root, someNumber)    

    def insertWithNode(self,node,someNumber):
        if node.lChild is None and node.rChild is None:#external node
            if someNumber > node.data:
                newNode = Node(someNumber)
                node.rChild = newNode
                newNode.parent = node
            else:
                newNode = Node(someNumber)
                node.lChild = newNode
                newNode.parent = node
        else: #not external
            if someNumber > node.data:
                if node.rChild is not None:
                    self.insertWithNode(node.rChild, someNumber)
                else: #if empty node
                    newNode = Node(someNumber)
                    node.rChild = newNode
                    newNode.parent = node 
            else:
                if node.lChild is not None:
                    self.insertWithNode(node.lChild, someNumber)
                else:
                    newNode = Node(someNumber)
                    node.lChild = newNode
                    newNode.parent = node                    

    def printTree(self,someNode):
        if someNode is None:
            pass
        else:
            self.printTree(someNode.lChild)
            print someNode.data
            self.printTree(someNode.rChild)

def main():  
    t = Tree()
    t.insert(5)  
    t.insert(3)
    t.insert(7)
    t.insert(4)
    t.insert(2)
    t.insert(1)
    t.insert(6)
    t.printTree(t.root)

if __name__ == '__main__':
    main()

Moje řešení.

Odpovězeno 26/03/2011 v 21:06
zdroj uživatelem

hlasů
6
class BST:
    def __init__(self, val=None):
        self.left = None
        self.right = None
        self.val = val

    def __str__(self):
        return "[%s, %s, %s]" % (self.left, str(self.val), self.right)

    def isEmpty(self):
        return self.left == self.right == self.val == None

    def insert(self, val):
        if self.isEmpty():
            self.val = val
        elif val < self.val:
            if self.left is None:
                self.left = BST(val)
            else:
                self.left.insert(val)
        else:
            if self.right is None:
                self.right = BST(val)
            else:
                self.right.insert(val)

a = BST(1)
a.insert(2)
a.insert(3)
a.insert(0)
print a
Odpovězeno 15/08/2012 v 03:31
zdroj uživatelem

hlasů
1

Další Python BST s klíč řazení (implicitně na hodnotě)

LEFT = 0
RIGHT = 1
VALUE = 2
SORT_KEY = -1

class BinarySearchTree(object):

    def __init__(self, sort_key=None):
        self._root = []  
        self._sort_key = sort_key
        self._len = 0  

def insert(self, val):
    if self._sort_key is None:
        sort_key = val // if no sort key, sort key is value
    else:
        sort_key = self._sort_key(val)

    node = self._root
    while node:
        if sort_key < node[_SORT_KEY]:
            node = node[LEFT]
        else:
            node = node[RIGHT]

    if sort_key is val:
        node[:] = [[], [], val]
    else:
        node[:] = [[], [], val, sort_key]
    self._len += 1

def minimum(self):
    return self._extreme_node(LEFT)[VALUE]

def maximum(self):
    return self._extreme_node(RIGHT)[VALUE]

def find(self, sort_key):
    return self._find(sort_key)[VALUE]

def _extreme_node(self, side):
    if not self._root:
        raise IndexError('Empty')
    node = self._root
    while node[side]:
        node = node[side]
    return node

def _find(self, sort_key):
    node = self._root
    while node:
        node_key = node[SORT_KEY]
        if sort_key < node_key:
            node = node[LEFT]
        elif sort_key > node_key:
            node = node[RIGHT]
        else:
            return node
    raise KeyError("%r not found" % sort_key)
Odpovězeno 29/04/2013 v 11:25
zdroj uživatelem

hlasů
1

Zde je kompaktní, objektově orientované, rekurzivní provádění:

    class BTreeNode(object):
        def __init__(self, data):
            self.data = data
            self.rChild = None
            self.lChild = None

    def __str__(self):
        return (self.lChild.__str__() + '<-' if self.lChild != None else '') + self.data.__str__() + ('->' + self.rChild.__str__() if self.rChild != None else '')

    def insert(self, btreeNode):
        if self.data > btreeNode.data: #insert left
            if self.lChild == None:
                self.lChild = btreeNode
            else:
                self.lChild.insert(btreeNode)
        else: #insert right
            if self.rChild == None:
                self.rChild = btreeNode
            else:
                self.rChild.insert(btreeNode)


def main():
    btreeRoot = BTreeNode(5)
    print 'inserted %s:' %5, btreeRoot

    btreeRoot.insert(BTreeNode(7))
    print 'inserted %s:' %7, btreeRoot

    btreeRoot.insert(BTreeNode(3))
    print 'inserted %s:' %3, btreeRoot

    btreeRoot.insert(BTreeNode(1))
    print 'inserted %s:' %1, btreeRoot

    btreeRoot.insert(BTreeNode(2))
    print 'inserted %s:' %2, btreeRoot

    btreeRoot.insert(BTreeNode(4))
    print 'inserted %s:' %4, btreeRoot

    btreeRoot.insert(BTreeNode(6))
    print 'inserted %s:' %6, btreeRoot

Výstup nad hlavní () je:

inserted 5: 5
inserted 7: 5->7
inserted 3: 3<-5->7
inserted 1: 1<-3<-5->7
inserted 2: 1->2<-3<-5->7
inserted 4: 1->2<-3->4<-5->7
inserted 6: 1->2<-3->4<-5->6<-7
Odpovězeno 04/09/2013 v 03:33
zdroj uživatelem

hlasů
2

Zjistil jsem, že řešení trochu neohrabaný na insertstraně. Dalo by se vrátit rootreferenci a zjednoduší to trochu:

def binary_insert(root, node):
    if root is None:
        return node
    if root.data > node.data:
        root.l_child = binary_insert(root.l_child, node)
    else:
        root.r_child = binary_insert(root.r_child, node)
    return root
Odpovězeno 24/09/2014 v 00:09
zdroj uživatelem

hlasů
-1

Zde je ukázka implementace, zda to pomohlo.

Odpovězeno 10/11/2015 v 15:12
zdroj uživatelem

hlasů
0

Následující kód je základní odpověď na @ DTing je a co se dozvím od třídy, který používá while vložit (označené v kódu).

class Node:
    def __init__(self, val):
        self.l_child = None
        self.r_child = None
        self.data = val


def binary_insert(root, node):
    y = None
    x = root
    z = node
    #while loop here
    while x is not None:
        y = x
        if z.data < x.data:
            x = x.l_child
        else:
            x = x.r_child
    z.parent = y
    if y == None:
        root = z
    elif z.data < y.data:
        y.l_child = z
    else:
        y.r_child = z


def in_order_print(root):
    if not root:
        return
    in_order_print(root.l_child)
    print(root.data)
    in_order_print(root.r_child)


r = Node(3)
binary_insert(r, Node(7))
binary_insert(r, Node(1))
binary_insert(r, Node(5))

in_order_print(r)
Odpovězeno 08/04/2016 v 10:19
zdroj uživatelem

hlasů
0

Zde je pracovní řešení.

class BST:
    def __init__(self,data):
        self.root = data
        self.left = None
        self.right = None

    def insert(self,data):
        if self.root == None:
            self.root = BST(data)
        elif data > self.root:
            if self.right == None:
                self.right = BST(data)
            else:
                self.right.insert(data)
        elif data < self.root:
            if self.left == None:
                self.left = BST(data)
            else:
                self.left.insert(data)

    def inordertraversal(self):
        if self.left != None:
            self.left.inordertraversal()
        print (self.root),
        if self.right != None:
            self.right.inordertraversal()

t = BST(4)
t.insert(1)
t.insert(7)
t.insert(3)
t.insert(6)
t.insert(2)
t.insert(5)
t.inordertraversal()
Odpovězeno 24/04/2017 v 19:22
zdroj uživatelem

hlasů
0

jeho snadné implementovat BST pomocí dvou tříd: 1. Uzel a 2. třídu Tree strom bude jen pro uživatelské rozhraní a skutečné metody budou implementovány ve třídě uzlu.

class Node():

    def __init__(self,val):
        self.value = val
        self.left = None
        self.right = None


    def _insert(self,data):
        if data == self.value:
            return False
        elif data < self.value:
            if self.left:
                return self.left._insert(data)
            else:
                self.left = Node(data)
                return True
        else:
            if self.right:
                return self.right._insert(data)
            else:
                self.right = Node(data)
                return True

    def _inorder(self):
        if self:
            if self.left:
                self.left._inorder()
            print(self.value)
            if self.right:
                self.right._inorder()



class Tree():

    def __init__(self):
        self.root = None

    def insert(self,data):
        if self.root:
            return self.root._insert(data)
        else:
            self.root = Node(data)
            return True
    def inorder(self):
        if self.root is not None:
            return self.root._inorder()
        else:
            return False




if __name__=="__main__":
    a = Tree()
    a.insert(16)
    a.insert(8)
    a.insert(24)
    a.insert(6)
    a.insert(12)
    a.insert(19)
    a.insert(29)
    a.inorder()

Nezbytného funkce pro kontrolu, zda je BST řádně provedena.

Odpovězeno 06/07/2017 v 08:37
zdroj uživatelem

hlasů
0

Přijatý odpověď zanedbává nastavit nadřazeného atribut pro každý uzel vložen, bez kterého nelze realizovat successorzpůsob, který najde nástupce v in-pořadí stromu procházku O ( h ) čas, kde h je výška stromu (na rozdíl k o ( n ) čas potřebný pro procházky).

Zde je implementace založený na pseudokódu uvedeného v CORMEN et al. Úvod do algoritmů , včetně postoupení parentatributu a successormetody:

class Node(object):
    def __init__(self, key):
        self.key = key
        self.left = None
        self.right = None
        self.parent = None


class Tree(object):
    def __init__(self, root=None):
        self.root = root

    def insert(self, z):
        y = None
        x = self.root
        while x is not None:
            y = x
            if z.key < x.key:
                x = x.left
            else:
                x = x.right
        z.parent = y
        if y is None:
            self.root = z       # Tree was empty
        elif z.key < y.key:
            y.left = z
        else:
            y.right = z

    @staticmethod
    def minimum(x):
        while x.left is not None:
            x = x.left
        return x

    @staticmethod
    def successor(x):
        if x.right is not None:
            return Tree.minimum(x.right)
        y = x.parent
        while y is not None and x == y.right:
            x = y
            y = y.parent
        return y

Zde jsou některé testy, které mají ukázat, že strom se chová podle očekávání na uvedeném příkladě by DTing :

import pytest

@pytest.fixture
def tree():
    t = Tree()
    t.insert(Node(3))
    t.insert(Node(1))
    t.insert(Node(7))
    t.insert(Node(5))
    return t

def test_tree_insert(tree):
    assert tree.root.key == 3
    assert tree.root.left.key == 1
    assert tree.root.right.key == 7
    assert tree.root.right.left.key == 5

def test_tree_successor(tree):
    assert Tree.successor(tree.root.left).key == 3
    assert Tree.successor(tree.root.right.left).key == 7

if __name__ == "__main__":
    pytest.main([__file__])
Odpovězeno 25/08/2017 v 10:42
zdroj uživatelem

hlasů
0

Problém, nebo alespoň jeden problém s váš kód je zde: -

def insert(self,node,someNumber):
    if node is None:
        node = Node(someNumber)
    else:
        if node.data > someNumber:
            self.insert(node.rchild,someNumber)
        else:
            self.insert(node.rchild, someNumber)
    return

Vidíte větu „pokud node.data> someNumber:“ as tím spojené „else“ prohlášení oba mají stejný kód, po nich. tedy děláte to samé, zda-li výrok je pravdivý či nepravdivý.

Doporučil bych vám nejspíš v úmyslu dělat různé věci tady, snad jeden z nich měl říci self.insert (node.lchild, someNumber)?

Odpovězeno 26/11/2018 v 16:21
zdroj uživatelem

hlasů
0

Dalším řešením Python BST

class Node(object):
    def __init__(self, value):
        self.left_node = None
        self.right_node = None
        self.value = value

    def __str__(self):
        return "[%s, %s, %s]" % (self.left_node, self.value, self.right_node)

    def insertValue(self, new_value):
        """
        1. if current Node doesnt have value then assign to self
        2. new_value lower than current Node's value then go left
        2. new_value greater than current Node's value then go right
        :return:
        """
        if self.value:
            if new_value < self.value:
                # add to left
                if self.left_node is None:  # reached start add value to start
                    self.left_node = Node(new_value)
                else:
                    self.left_node.insertValue(new_value)  # search
            elif new_value > self.value:
                # add to right
                if self.right_node is None:  # reached end add value to end
                    self.right_node = Node(new_value)
                else:
                    self.right_node.insertValue(new_value)  # search
        else:
            self.value = new_value

    def findValue(self, value_to_find):
        """
        1. value_to_find is equal to current Node's value then found
        2. if value_to_find is lower than Node's value then go to left
        3. if value_to_find is greater than Node's value then go to right
        """
        if value_to_find == self.value:
            return "Found"
        elif value_to_find < self.value and self.left_node:
            return self.left_node.findValue(value_to_find)
        elif value_to_find > self.value and self.right_node:
            return self.right_node.findValue(value_to_find)
        return "Not Found"

    def printTree(self):
        """
        Nodes will be in sequence
        1. Print LHS items
        2. Print value of node
        3. Print RHS items
        """
        if self.left_node:
            self.left_node.printTree()
        print(self.value),
        if self.right_node:
            self.right_node.printTree()

    def isEmpty(self):
        return self.left_node == self.right_node == self.value == None


def main():
    root_node = Node(12)
    root_node.insertValue(6)
    root_node.insertValue(3)
    root_node.insertValue(7)

    # should return 3 6 7 12
    root_node.printTree()

    # should return found
    root_node.findValue(7)
    # should return found
    root_node.findValue(3)
    # should return Not found
    root_node.findValue(24)

if __name__ == '__main__':
    main()
Odpovězeno 14/04/2019 v 15:07
zdroj uživatelem

hlasů
0
    def BinaryST(list1,key):
    start = 0
    end = len(list1)
    print("Length of List: ",end)

    for i in range(end):
        for j in range(0, end-i-1):
            if(list1[j] > list1[j+1]):
                temp = list1[j]
                list1[j] = list1[j+1]
                list1[j+1] = temp

    print("Order List: ",list1)

    mid = int((start+end)/2)
    print("Mid Index: ",mid)

    if(key == list1[mid]):
        print(key," is on ",mid," Index")

    elif(key > list1[mid]):
        for rindex in range(mid+1,end):
            if(key == list1[rindex]):
                print(key," is on ",rindex," Index")
                break
            elif(rindex == end-1):
                print("Given key: ",key," is not in List")
                break
            else:
                continue

    elif(key < list1[mid]):
        for lindex in range(0,mid):
            if(key == list1[lindex]):
                print(key," is on ",lindex," Index")
                break
            elif(lindex == mid-1):
                print("Given key: ",key," is not in List")
                break
            else:
                continue


size = int(input("Enter Size of List: "))
list1 = []
for e in range(size):
    ele = int(input("Enter Element in List: "))
    list1.append(ele)

key = int(input("\nEnter Key for Search: "))

print("\nUnorder List: ",list1)
BinaryST(list1,key)
Odpovězeno 02/01/2020 v 17:20
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more