Skip to content

Instantly share code, notes, and snippets.

@crf1028
Last active November 17, 2016 09:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crf1028/9b315446d985714a168a9cdb5cb46cef to your computer and use it in GitHub Desktop.
Save crf1028/9b315446d985714a168a9cdb5cb46cef to your computer and use it in GitHub Desktop.
Data structure in python
class CustomBinaryHeap:
"""binary heap(bh) implementation in python"""
def __init__(self, data):
"""initialize bh"""
if not isinstance(data, list):
raise TypeError('Must be a list.')
if data is []:
raise TypeError('Must not be empty.')
self._data = data
self._complete_tree()
def __repr__(self):
"""print tree in array form"""
return str(self._data)
def _get_parent_index(self, index):
"""get the index of parent node"""
if index > self._data.__len__():
raise IndexError("node does not exist")
if index % 2 == 0:
return index / 2
elif index == 1:
return None
else:
return (index - 1) / 2
def _get_last_internal_node(self):
"""get the last internal node"""
_length = self._data.__len__()
if _length % 2 == 0:
return _length / 2
elif _length == 1:
return None
else:
return (_length - 1) / 2
def _get_left_child_index(self, index):
"""get the index of left child"""
if index > self._get_last_internal_node():
raise IndexError('leaf node')
else:
return 2 * index
def _get_right_child_index(self, index):
"""get the index of right child"""
_rc = self._get_left_child_index(index) + 1
if _rc > self._data.__len__():
raise IndexError('does not have right child')
else:
return _rc
def _get_item(self, index):
"""get the tree element by index"""
return self._data[index-1]
def _sift_up(self, index):
"""swap current node with parent node"""
if self._get_item(index) > self._get_item(self._get_parent_index(index)):
self._data[index-1], self._data[self._get_parent_index(index)-1] = \
self._data[self._get_parent_index(index)-1], self._data[index-1]
if index < 4:
pass
elif index % 2 == 0:
return self._sift_up(index/2)
else:
return self._sift_up((index-1)/2)
def _sift_down(self, index):
"""find the max node and make it the parent node"""
_cur_par = self._get_item(index)
_cur_l_c = self._get_item(self._get_left_child_index(index))
try:
_cur_r_c = self._get_item(self._get_right_child_index(index))
except IndexError:
_cur_r_c = _cur_par - 1
_max = max(_cur_par, _cur_l_c, _cur_r_c)
if _max == _cur_par:
pass
elif _max == _cur_l_c:
self._data[index-1], self._data[self._get_left_child_index(index)-1] = \
self._data[self._get_left_child_index(index)-1], self._data[index-1]
if index * 2 <= self._get_last_internal_node():
return self._sift_down(index * 2)
elif _max == _cur_r_c:
self._data[index - 1], self._data[self._get_right_child_index(index) - 1] = \
self._data[self._get_right_child_index(index) - 1], self._data[index - 1]
if index * 2 + 1 <= self._get_last_internal_node():
return self._sift_down(index * 2 + 1)
def _complete_tree(self):
"""make a heap tree in order"""
_last_internal_node = self._get_last_internal_node()
for i in range(_last_internal_node, 0, -1):
self._sift_down(i)
def insert(self, data):
"""insert at the end"""
self._data.append(data)
self._sift_up(self._data.__len__())
def get_max(self):
"""get the maximum element"""
return self._data[0]
def extract_max(self):
"""return and delete the maximum element"""
if self._data.__len__() <= 2:
raise IndexError('too few elements')
self._data[0], self._data[self._data.__len__()-1] = self._data[self._data.__len__()-1], self._data[0]
_temp = self._data.pop()
self._sift_down(1)
return _temp
def len(self):
"""
get the length of binary heap
:return integer
"""
return self._data.__len__()
def delete(self, index):
"""delete element by index"""
if self._data.__len__() <= 3:
raise IndexError('too few elements')
_max = self.get_max()
self._data[index-1] = _max + 1
self._sift_up(index)
self.extract_max()
if __name__ == '__main__' and TEST == 4:
a = [1,3,2,9,6,44,8,67,21]
b = CustomBinaryHeap(a)
print a
b.insert(88)
b.insert(22)
print a
b.extract_max()
print b
b.delete(3)
print b
class BSTNode:
"""node for binary search tree"""
def __init__(self, data=None):
"""initialize"""
if data is not None:
self.data = data
self.parent_node = None
self.left_child = None
self.right_child = None
def __repr__(self):
"""print data of node"""
return str(self.data)
def append2left(self, n_node):
"""append child to left node of parent"""
self.left_child = n_node
n_node.parent_node = self
def append2right(self, n_node):
"""append child to right node of parent"""
self.right_child = n_node
n_node.parent_node = self
def unbind_from_parent_and_set_free(self):
"""delete parent's link to child and child's link to parent"""
if self.parent_node is not None:
parent = self.parent_node
if parent.left_child == self:
parent.left_child = None
elif parent.right_child == self:
parent.right_child = None
else:
raise StandardError("unknown error")
self.parent_node = None
def _bind_new_child(self, parent, old_child, new_child):
pass
class CustomBinarySearchTree:
"""binary search tree(bst) implementation in python"""
def __init__(self):
"""initialize"""
self._root = None
self._size = 0
def __repr__(self):
return "print function is not implemented yet"
def insert(self, node):
"""insert into tree"""
if not isinstance(node, BSTNode):
raise TypeError
if self._size == 0:
self._root = node
else:
_result = self.find(node.data, _cur_n=self._root, mode="insert")
if _result.data == node.data:
raise StandardError("duplicate node")
if _result.data > node.data:
_result.append2left(node)
elif _result.data < node.data:
_result.append2right(node)
self._size += 1
def find(self, data2f, _cur_n=None, mode="find"):
"""
find some data in three modes
return the node if found
return False if not found
"""
if _cur_n is None:
_cur_n = self._root
if _cur_n.data == data2f:
return _cur_n
elif _cur_n.data < data2f:
if _cur_n.right_child:
return self.find(data2f, _cur_n.right_child, mode=mode)
else:
return self._router(mode, data2f, _cur_n)
elif _cur_n.data > data2f:
if _cur_n.left_child:
return self.find(data2f, _cur_n.left_child, mode=mode)
else:
return self._router(mode, data2f, _cur_n)
else:
raise StandardError("can't find target")
def find_next(self, data2f):
"""
find the next element
return the next node if found
return False if not found
"""
return self.find(data2f+1, mode="find_next")
def _is_largest_node(self, node):
"""find whether node is the largest node"""
if node.right_child:
return False
if self._root == node:
return True
if self._most_left_ancestor(node) == self._root:
return True
def _most_left_ancestor(self, node):
"""find the most left ancestor of a node"""
if not node.parent_node:
return node
if node.parent_node.right_child == node:
return self._most_left_ancestor(node.parent_node)
else:
return node
def _router(self, mode, data2f, _cur_n):
"""route find function to three routes"""
if mode == "find":
return False
elif mode == "insert":
return _cur_n
elif mode == "find_next":
if self._is_largest_node(_cur_n) and data2f >= _cur_n.data:
return False
return self._find_1st_bigger_ancestor(_cur_n, data2f)
else:
raise StandardError("unknown error")
def _find_1st_bigger_ancestor(self, node, data2f):
"""find the first ancestor that is bigger than data2f"""
if not node.parent_node:
return node
if node.data > data2f:
return node
else:
return self._find_1st_bigger_ancestor(node.parent_node, data2f)
def range_search(self, start, end):
"""search tree during a range"""
_range = []
_cur = self.find(start, mode="find_next").data
while _cur and _cur <= end:
_range.append(_cur)
try:
_cur = self.find_next(_cur).data
except AttributeError:
_cur = False
return _range
def delete(self, data2d):
"""delete some data"""
result = self.find(data2d)
if not result:
raise StandardError("can't find data in the tree")
if not result.left_child and not result.right_child:
if result.parent_node:
result.unbind_from_parent_and_set_free()
else:
self._root = None
elif not result.right_child:
if result.parent_node:
if result.parent_node.left_child == result:
result.parent_node.append2left(result.left_child)
elif result.parent_node.right_child == result:
result.parent_node.append2right(result.left_child)
result.parent_node = None
result.left_child = None
else:
self._root = result.left_child
result.left_child.parent_node = None
result.left_child = None
elif not result.left_child:
if result.parent_node:
if result.parent_node.left_child == result:
result.parent_node.append2left(result.right_child)
elif result.parent_node.right_child == result:
result.parent_node.append2right(result.right_child)
result.parent_node = None
result.right_child = None
else:
self._root = result.right_child
result.right_child.parent_node = None
result.right_child = None
else:
next_of_result = self.find_next(result.data)
if next_of_result.right_child:
next_of_result.parent_node.left_child = next_of_result.right_child
next_of_result.right_child.parent_node = next_of_result.parent_node
else:
next_of_result.parent_node.left_child = None
if result.parent_node:
if result.parent_node.left_child == result:
result.parent_node.append2left(next_of_result)
elif result.parent_node.right_child == result:
result.parent_node.append2right(next_of_result)
next_of_result.left_child = result.left_child
result.left_child.parent_node = next_of_result
next_of_result.right_child = result.right_child
result.right_child.parent_node = next_of_result
else:
self._root = next_of_result
next_of_result.left_child = result.left_child
result.left_child.parent_node = next_of_result
next_of_result.right_child = result.right_child
result.right_child.parent_node = next_of_result
result.__init__()
self._size -= 1
if __name__ == '__main__' and TEST == 5:
from random import randint
b = CustomBinarySearchTree()
for i in range(5):
print i
b.insert(BSTNode(randint(1, 1000)))
b.insert(BSTNode(7))
b.insert(BSTNode(999))
print b.find(7)
print b.find_next(6)
print b.find_next(997)
print b.find_next(999)
print b.find(998)
b.delete(999)
b.delete(7)
print b.range_search(1, 1000)
class CustomDisjointSet:
"""disjoint set(ds) implementation in python"""
def __init__(self):
"""initialize"""
self.data = None
self.parent = None
self.id = None
def __repr__(self):
"""print data of set"""
return str(self.data)
def make_set(self, item):
"""make set out of some data"""
if self.data:
raise StandardError("set is not empty")
self.data = item
self.parent = self
def union(self, target):
"""union two sets"""
if not isinstance(target, CustomDisjointSet):
raise TypeError("target is not disjoint set")
if self.find_set().data > target.find_set().data:
target.find_set().parent = self.parent
else:
self.find_set().parent = target.parent
def find_set(self):
"""find the id of some set"""
if self.parent == self:
return self
if self.parent.parent != self.parent:
self.parent = self.parent.parent
return self.find_set()
else:
return self.parent
if __name__ == '__main__' and TEST == 6:
a = CustomDisjointSet()
a.make_set(4)
b = CustomDisjointSet()
b.make_set(7)
a.union(b)
c = CustomDisjointSet()
c.make_set(10)
print a.find_set()
c.union(a)
print a.find_set()
print b.find_set()
class DLLNode(LLNode):
"""node for doubly linked list"""
def __init__(self, data=None):
LLNode.__init__(self, data)
self._pre_node = None
def append(self, n_node):
"""append n_node to self and make links"""
self._next_node = n_node
n_node._pre_node = self
def pre_n(self):
""":return previous node"""
return self._pre_node
def make_it_head(self, n_node=None):
"""make a LLNode the head of linked list, and append some node to it"""
if isinstance(n_node, DLLNode):
self.append(n_node)
n_node.is_head = False
elif n_node is None:
pass
else:
raise TypeError
self.is_head = True
self._pre_node = None
def concat(self, pre_node, n_node):
"""insert self into two linked nodes"""
self._next_node = n_node
self._pre_node = pre_node
pre_node._next_node = self
n_node._pre_node = self
class CustomDoublyLinkedList(CustomLinkedList):
"""doubly linked list(dll) implementation in python"""
def __init__(self):
"""initialize dll"""
CustomLinkedList.__init__(self)
def _find_previous_node(self, node):
"""find the previous node of node"""
if self.find(node):
return node.pre_n()
else:
return False
if __name__ == '__main__' and TEST == 2:
a = DLLNode('ss')
b = CustomDoublyLinkedList()
b.push_back(a)
print b
print b.len()
b.pop_back()
print b
print b.len()
b.push_front(DLLNode('1'))
b.push_back(DLLNode('2'))
print b
print b.len()
b.push_back(a)
b.add_after(a, DLLNode('5'))
print b
print b.len()
b.add_before(a, DLLNode('6'))
print b
print b.len()
b.pop_back()
print b
print b.len()
b.pop_back()
print b
print b.len()
b.pop_front()
print b
print b.len()
class LLNode:
"""basic node for linked list"""
def __init__(self, data=None):
"""initialize LLNode"""
if data is not None:
self._data = data
self.is_head = False
self.is_tail = False
self._next_node = None
def __repr__(self):
"""print data of node"""
return str(self._data)
def make_it_head(self, n_node=None):
"""make a LLNode the head of linked list, and append some node to it"""
if isinstance(n_node, LLNode):
self.append(n_node)
n_node.is_head = False
elif n_node is None:
pass
else:
raise TypeError
self.is_head = True
def make_it_tail(self, p_node=None):
"""make a LLNode the tail of linked list, and append it to some node"""
if isinstance(p_node, LLNode):
p_node.append(self)
p_node.is_tail = False
elif p_node is None:
pass
else:
raise TypeError
self.is_tail = True
self._next_node = None
def append(self, n_node):
"""append a node"""
self._next_node = n_node
def next_n(self):
"""return next node"""
return self._next_node
def concat(self, pre_node, n_node):
"""insert self into two linked nodes"""
self._next_node = n_node
pre_node._next_node = self
class CustomLinkedList: # TODO debug, maybe real pointer in the future
"""linked list(ll) implementation in python"""
def __init__(self):
"""initialize ll"""
self._head_node = None
self._tail_node = None
self._length = 0
def __repr__(self):
"""print ll"""
cur_node = self._head_node
out_put = ''
while cur_node is not None:
out_put += str(cur_node) + ' ~ '
cur_node = cur_node.next_n()
return out_put
def push_front(self, node):
"""add node to the front"""
if not isinstance(node, LLNode):
raise TypeError
node.make_it_head(self._head_node)
self._head_node = node
if self._length == 0:
node.make_it_tail()
self._tail_node = node
self._length += 1
def top(self):
"""return the top element"""
return self._head_node
def pop_front(self):
"""delete and return the top element"""
self._empty_error_msg()
old_head = self._head_node
if self._length == 1:
self.__init__()
else:
self._head_node = self._head_node.next_n()
self._head_node.make_it_head()
self._length -= 1
old_head.__init__()
return old_head
def push_back(self, node):
"""add node to the end"""
if not isinstance(node, LLNode):
raise TypeError
node.make_it_tail(self._tail_node)
self._tail_node = node
if self._length == 0:
node.make_it_head()
self._head_node = node
self._length += 1
def end(self):
"""return the end element"""
return self._tail_node
def pop_back(self):
"""delete and return the last element"""
self._empty_error_msg()
old_tail = self._tail_node
if self._length == 1:
self.__init__()
else:
self._tail_node = self._find_previous_node(old_tail)
self._tail_node.make_it_tail()
self._length -= 1
old_tail.__init__()
return old_tail
def find(self, data2f):
"""check whether some data is inside ll"""
self._empty_error_msg()
current_node = self._head_node
while current_node:
if str(current_node) == str(data2f):
return True
current_node = current_node.next_n()
def delete(self, data2d):
"""find some data inside ll and delete it"""
self._empty_error_msg()
previous_node = None
current_node = self._head_node
try:
next_node = current_node.next_n()
except AttributeError:
next_node = None
while current_node:
if str(current_node) == str(data2d):
if self._length == 1:
self.__init__()
elif previous_node is None:
self._head_node = next_node
self._head_node.make_it_head()
elif next_node is None:
self._tail_node = previous_node
self._tail_node.make_it_tail()
else:
previous_node.append(next_node)
self._length -= 1
current_node.__init__()
break
previous_node = current_node
current_node = next_node
else:
raise IndexError("Could not find data to delete.")
def len(self):
"""get the length of ll"""
return self._length
def add_before(self, tar_node, node):
"""insert node before target node"""
if not isinstance(node, LLNode) or not isinstance(tar_node, LLNode):
raise TypeError
pre_node = self._find_previous_node(tar_node)
if pre_node is False:
raise IndexError("Could not find target node.")
elif pre_node is None:
self._head_node = node
node.make_it_head(tar_node)
else:
node.concat(pre_node, tar_node)
self._length += 1
def add_after(self, tar_node, node):
"""insert node after target node"""
if not isinstance(node, LLNode) or not isinstance(tar_node, LLNode):
raise TypeError
if tar_node.next_n() is None:
node.make_it_tail(tar_node)
self._tail_node = node
else:
node.concat(tar_node, tar_node.next_n())
self._length += 1
def _find_previous_node(self, node):
"""find the previous node of some node"""
self._empty_error_msg()
if not isinstance(node, LLNode):
raise TypeError
current_node = self._head_node
while current_node.next_n():
if current_node.next_n() == node:
return current_node
current_node = current_node.next_n()
else:
return False
def is_empty(self):
"""check whether ll is empty"""
if self._length == 0:
return True
else:
return False
def _empty_error_msg(self):
"""raise an error when ll is empty"""
if self.is_empty():
raise IndexError("linked list is empty")
if __name__ == '__main__' and TEST == 1:
a = LLNode('ss')
b = CustomLinkedList()
b.push_back(a)
print b
print b.len()
b.pop_back()
print b
print b.len()
b.push_front(LLNode('1'))
b.push_back(LLNode('2'))
print b
print b.len()
b.push_back(a)
b.add_after(a, LLNode('5'))
print b
print b.len()
b.add_before(a, LLNode('6'))
print b
print b.len()
b.pop_back()
print b
print b.len()
b.pop_back()
print b
print b.len()
class CustomPriorityQ(CustomDoublyLinkedList):
"""priority queue(pq) implementation in python"""
def __init__(self):
"""initialize pq"""
CustomDoublyLinkedList.__init__(self)
self._max_p_node = None
def insert(self, node):
"""insert node at the end"""
self.push_back(node)
if self._max_p_node is None:
self._max_p_node = node
elif str(self._max_p_node) < str(node):
self._max_p_node = node
def extract_max(self):
"""return the max node and delete it"""
old_max = self._max_p_node
pre_max = old_max.pre_n()
max_n = old_max.next_n()
if old_max.is_head is True:
max_n.is_head = True
elif old_max.is_tail is True:
pre_max.is_tail = True
old_max.__init__()
pre_max.append(max_n)
self._max_p_node = self._find_max()
return old_max
def get_max(self):
"""return the max node"""
if self._max_p_node:
return self._max_p_node
else:
raise IndexError("Queue is empty.")
def _find_max(self):
"""find the max node"""
cur_n = self._head_node
max_n = cur_n
while cur_n.next_n():
if max_n < cur_n.next_n():
max_n = cur_n.next_n()
cur_n = cur_n.next_n()
return max_n
class CustomQueue:
"""Queue implementation in python"""
_Queue_Capacity = 10
def __init__(self):
"""initialize Queue"""
self._data = [None] * self._Queue_Capacity
self._length = 0
self._front = 0
self._rear = 9
def __repr__(self):
"""print Queue"""
return str(self._data)
def is_full(self):
"""check whether Queue is full"""
return self._length == self._Queue_Capacity
def is_empty(self):
"""check whether Queue is empty"""
return not bool(self._length)
def len(self):
"""return the length of Queue"""
return self._length
def enqueue(self, item):
"""add element to Queue"""
if self.is_full():
self._resize()
if self._rear == self._Queue_Capacity - 1:
self._rear = 0
else:
self._rear += 1
self._data[self._rear] = item
self._length += 1
def dequeue(self):
"""delete the and return the top element"""
if self.is_empty():
raise IndexError("The Stack is empty!")
_temp = self._data[self._front]
self._data[self._front] = None
if self._front == self._Queue_Capacity - 1:
self._front = 0
else:
self._front += 1
self._length -= 1
return _temp
def front(self):
"""return the top element"""
if self.is_empty():
raise IndexError("The Stack is empty!")
return self._data[self._front]
def _resize(self):
"""resize Queue at full"""
_new_data = [None] * 10
for i in range(self._front, self._Queue_Capacity):
_new_data.append(self._data[i])
for i in range(0, self._front):
_new_data.append(self._data[i])
self._data = _new_data
self._Queue_Capacity += 10
self._front = 10
self._rear = self._Queue_Capacity - 1
class CustomStack:
"""Stack implementation in python"""
def __init__(self):
"""initialize Stack"""
self._data = []
def __repr__(self):
"""print Stack function"""
return str(self._data)
def is_empty(self):
"""determine whether Stack is empty"""
return not bool(self._data.__len__())
def len(self):
"""return the length of Stack"""
return self._data.__len__()
def push(self, item):
"""add element to Stack"""
self._data.append(item)
def pop(self):
"""delete and return the top element"""
if self.is_empty():
raise IndexError("The Stack is empty!")
return self._data.pop()
def top(self):
"""return the top element"""
if self.is_empty():
raise IndexError("The Stack is empty!")
return self._data[-1]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment