blob: eb94104b77508c19130a900d69d50165aaae1516 [file] [log] [blame]
#!/usr/bin/env python
#coding:utf-8
# Author: mozman
# Purpose: tree walker for cython trees
# Created: 07.05.2010
# Copyright (c) 2010-2013 by Manfred Moitzi
# License: MIT License
DEF MAXSTACK=32
from stack cimport *
from ctrees cimport *
cdef class cWalker:
def __cinit__(self):
self.root = NULL
self.node = NULL
self.stack = stack_init(MAXSTACK)
def __dealloc__(self):
stack_delete(self.stack)
cdef void set_tree(self, node_t *root):
self.root = root
self.reset()
cpdef reset(self):
stack_reset(self.stack)
self.node = self.root
@property
def key(self):
return <object> self.node.key
@property
def value(self):
return <object> self.node.value
@property
def item(self):
return (<object>self.node.key, <object>self.node.value)
@property
def is_valid(self):
return self.node != NULL
def goto(self, key):
cdef int cval
self.node = self.root
while self.node != NULL:
cval = ct_compare(key, <object> self.node.key)
if cval == 0:
return True
elif cval < 0:
self.node = self.node.link[0]
else:
self.node = self.node.link[1]
return False
cpdef push(self):
stack_push(self.stack, self.node)
cpdef pop(self):
if stack_is_empty(self.stack) != 0:
raise IndexError('pop(): stack is empty')
self.node = stack_pop(self.stack)
def stack_is_empty(self):
return <bint> stack_is_empty(self.stack)
def goto_leaf(self):
""" get a leaf node """
while self.node != NULL:
if self.node.link[0] != NULL:
self.node = self.node.link[0]
elif self.node.link[1] != NULL:
self.node = self.node.link[1]
else:
return
def has_child(self, int direction):
return self.node.link[direction] != NULL
def down(self, int direction):
self.node = self.node.link[direction]
def go_left(self):
self.node = self.node.link[0]
def go_right(self):
self.node = self.node.link[1]
def has_left(self):
return self.node.link[0] != NULL
def has_right(self):
return self.node.link[1] != NULL
def succ_item(self, key):
""" Get successor (k,v) pair of key, raises KeyError if key is max key
or key does not exist.
"""
self.node = ct_succ_node(self.root, key)
if self.node == NULL: # given key is biggest in tree
raise KeyError(str(key))
return (<object> self.node.key, <object> self.node.value)
def prev_item(self, key):
""" Get predecessor (k,v) pair of key, raises KeyError if key is min key
or key does not exist.
"""
self.node = ct_prev_node(self.root, key)
if self.node == NULL: # given key is smallest in tree
raise KeyError(str(key))
return (<object> self.node.key, <object> self.node.value)
def floor_item(self, key):
""" Get the element (k,v) pair associated with the greatest key less
than or equal to the given key, raises KeyError if there is no such key.
"""
self.node = ct_floor_node(self.root, key)
if self.node == NULL: # given key is smaller than min-key in tree
raise KeyError(str(key))
return (<object> self.node.key, <object> self.node.value)
def ceiling_item(self, key):
""" Get the element (k,v) pair associated with the smallest key greater
than or equal to the given key, raises KeyError if there is no such key.
"""
self.node = ct_ceiling_node(self.root, key)
if self.node == NULL: # given key is greater than max-key in tree
raise KeyError(str(key))
return (<object> self.node.key, <object> self.node.value)