#!/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 self.node.key @property def value(self): return self.node.value @property def item(self): return (self.node.key, 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, 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 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 ( self.node.key, 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 ( self.node.key, 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 ( self.node.key, 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 ( self.node.key, self.node.value)