#!/usr/bin/env python
class SequentialSearchDict(object):
class Node(object):
def __init__(self, key, value):
self.key = key
self.value = value
self.next = None
def __init__(self):
self.first = None
self.size = 0
def put(self, key, value):
self._put(key, value)
def _put(self, key, value):
n = self._get(key)
if n:
n.value = value
return 0
else:
# add the new node into the first
tmp = self.first
self.first = SequentialSearchDict.Node(key, value)
self.first.next = tmp
self.size += 1
return 1
def _get(self, key):
n = self.first
while n:
if n.key == key: return n
n = n.next
return None
def get(self, key):
n = self._get(key)
if n: return n.value
return n
class BinarySearchDict(object):
class Node(object):
def __init__(self, key, value):
self.key = key
self.value = value
def __init__(self):
self.size = 0
self.l = []
def put(self, key, value):
# the elements must be kept sorted for the binary search to work
index = self._get(key)
if index < 0:
self.l.append(BinarySearchDict.Node(key, value))
self.size += 1
return
n = self.l[index]
if n.key == key:
n.value = value
else:
self.l.append(BinarySearchDict.Node(key, value))
# shift all the elements to the right
if (index+1) < (len(self.l)-1):
for i in xrange(len(self.l)-1, index, -1):
self.l[i] = self.l[i-1]
self.size += 1
def get(self, key):
# search using binary search
index = self._get(key)
if index < 0: return None
n = self.l[index]
if n.key == key: return n.value
return None
def _get(self, key):
lo = 0
hi = len(self.l) - 1
mid = (lo + hi) / 2
while lo <= mid and hi >= mid:
if self.l[mid].key > key:
hi = mid - 1
mid = (lo + hi) / 2
elif self.l[mid].key == key:
return mid
elif self.l[mid].key < key:
lo = mid + 1
mid = (lo + hi) / 2
return mid
class BinarySearchTreeDict(object):
class Node(object):
def __init__(self, key, value):
self.key = key
self.value = value
self.left = None
self.right = None
def __init__(self):
self.size = 0
self.root = None
def put(self, key, value):
self.root = self._put(key, value, self.root)
def get(self, key):
return self._get(key, self.root)
def _put(self, key, value, node):
if node == None:
self.size += 1
return BinarySearchTreeDict.Node(key, value)
if node.key == key:
node.value = value
return node
elif node.key < key: node.left = self._put(key, value, node.left)
else: node.right = self._put(key, value, node.right)
return node
def _get(self, key, node):
if node == None: return None
if node.key == key: return node.value
elif node.key < key: return self._get(key, node.left)
else: return self._get(key, node.right)
class BalancedSearchTreeDict(object):
class Node(object):
RED = True
BLACK = False
def __init__(self, key, value):
self.key = key
self.value = value
self.left = None
self.right = None
self.color = BalancedSearchTreeDict.Node.RED
def is_red(self, node):
if node == None: return False
return node.color == BalancedSearchTreeDict.Node.RED
def rotate_left(self, node):
x = node.right
node.right = x.left
x.left = node
node.color = BalancedSearchTreeDict.Node.RED
return x
def rotate_right(self, node):
x = node.left
node.left = x.right
x.right = node
node.color = BalancedSearchTreeDict.Node.RED
return x
def flip_colors(self, node):
node.color = BalancedSearchTreeDict.Node.RED
node.left.color = BalancedSearchTreeDict.Node.BLACK
node.right.color = BalancedSearchTreeDict.Node.BLACK
def __init__(self):
self.size = 0
self.root = None
def put(self, key, value):
self.root = self._put(key, value, self.root)
self.root.color = BalancedSearchTreeDict.Node.BLACK
def _put(self, key, value, node):
if node == None:
self.size += 1
return BalancedSearchTreeDict.Node(key, value)
if node.key == key:
node.value = value
return node
elif node.key < key: node.left = self._put(key, value, node.left)
else: node.right = self._put(key, value, node.right)
# these are the properties of Red-Black tree for balancing
# the tree
if node.is_red(node.right) and not node.is_red(node.left):
node = node.rotate_left(node);
if node.is_red(node.left) and node.is_red(node.left.left):
node = node.rotate_right(node);
if node.is_red(node.left) and node.is_red(node.right):
node.flip_colors(node);
return node
def get(self, key):
return self._get(key, self.root)
def _get(self, key, node):
if node == None: return None
if node.key == key: return node.value
elif node.key < key: return self._get(key, node.left)
else: return self._get(key, node.right)
class HashDict(object):
# choose this M to be a prime number
M = 977
def __init__(self, n=M):
self.size = 0
self.l = []
for i in xrange(0, n):
self.l.append(SequentialSearchDict())
def _hash(self, key):
return (hash(key) & 0x7ffffff) % HashDict.M
def put(self, key, value):
d = self.l[self._hash(key)]
n = d._put(key, value)
self.size += n
def get(self, key):
return self.l[self._hash(key)].get(key)
if __name__ == "__main__":
searches = [SequentialSearchDict(),
BinarySearchDict(),
BinarySearchTreeDict(),
BalancedSearchTreeDict(),
HashDict()]
for s in searches:
assert None == s.get("foo")
s.put("1", "a")
s.put("2", "b")
s.put("3", "c")
assert 3 == s.size
assert "b" == s.get("2")
assert "c" == s.get("3")
assert "a" == s.get("1")
s.put("3", "d")
assert 3 == s.size
assert "d" == s.get("3")
assert "b" == s.get("2")
assert "a" == s.get("1")
assert None == s.get("bar")
Sunday, May 20, 2012
Search Algorithms in Python
Below are some popular implementations of searching algorithms.
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment