-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Python algorithms and data structures
- Loading branch information
Showing
25 changed files
with
1,059 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
# Binary search tree property: Left node is smaller than parent, right node is larger than parent | ||
import random | ||
class Node: | ||
def __init__(self, key): | ||
self.key = key | ||
self.left = None | ||
self.right = None | ||
self.parent = None | ||
|
||
def __str__(self): | ||
return str(self.key) | ||
|
||
def __repr__(self): | ||
return str(self.key) | ||
|
||
class BinaryTree: | ||
|
||
def __init__(self, root): | ||
self.root = root | ||
|
||
def inorder_tree_walk(self, root): # Writes all numbers in increasing order | ||
if root is not None: | ||
self.inorder_tree_walk(root.left) | ||
print("Key: " + str(root.key) + ", left: " + str(root.left) + ", right: " + str(root.right) + ", parent: " + str(root.parent)) | ||
self.inorder_tree_walk(root.right) | ||
|
||
def tree_minimum(self, root): | ||
while root.left is not None: | ||
root = root.left | ||
return root | ||
|
||
def tree_maximum(self, root): | ||
while root.right is not None: | ||
root = root.right | ||
return root | ||
|
||
def tree_search(self, root, key): | ||
while root is not None and key is not root.key: | ||
if key < root.key: | ||
root = root.left | ||
else: | ||
root = root.right | ||
return root | ||
|
||
def tree_successor(self, node): # Returns the node with the bigger key than the argument node | ||
if node.right is not None: | ||
return self.tree_minimum(node.right) | ||
p = node.parent | ||
while p is not None and node is p.right: | ||
# "Go up one level" | ||
node = p | ||
p = p.parent | ||
return p | ||
|
||
|
||
def insert(self, T, node): | ||
y = None | ||
root = T.root | ||
while root is not None: | ||
y = root | ||
if node.key < root.key: | ||
root = root.left | ||
else: | ||
root = root.right | ||
node.parent = y | ||
if y is None: # The new node is the root | ||
T.root = node | ||
elif node.key < y.key: | ||
y.left = node | ||
else: | ||
y.right = node | ||
|
||
def transplant(self, T, u, v): # Replaces subtree rooted at u with subtree rooted at v | ||
if u.parent == None: | ||
T.root = v | ||
elif u == u.parent.left: | ||
u.parent.left = v | ||
else: | ||
u.parent.right = v | ||
if v is not None: | ||
v.parent = u.parent | ||
|
||
def delete(self, T, node): | ||
if node.left is None: | ||
self.transplant(T,node,node.right) # Swap out subtree rooted at node with subtree rooted at node.right | ||
elif node.right is None: | ||
self.transplant(T, node, node.left) # Swap out subtree rooted at node with subtree rooted at node.right | ||
else: | ||
y = self.tree_minimum(node.right) | ||
if y.parent != node: | ||
self.transplant(T,y,y.right) | ||
y.right = node.right | ||
y.right.parent = y | ||
self.transplant(T,node,y) | ||
y.left = node.left | ||
y.left.parent = y | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
rootNode = Node(5) | ||
binTree = BinaryTree(rootNode) | ||
nodeList = [rootNode] | ||
for i in range(5): | ||
n = Node(random.randint(-10,10)) | ||
nodeList.append(n) | ||
binTree.insert(binTree, n) | ||
|
||
|
||
print(nodeList) | ||
print("Before:") | ||
binTree.inorder_tree_walk(binTree.root) | ||
print("\n") | ||
print("After:") | ||
print(type(nodeList[0])) | ||
binTree.delete(binTree,nodeList[0]) | ||
binTree.inorder_tree_walk(binTree.root) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
class Node: | ||
def __init__(self, key, satellite_data): | ||
self.key = key | ||
self.satellite_data = satellite_data | ||
|
||
def __str__(self): | ||
return str(self.key) + " : " + str(self.satellite_data) | ||
|
||
class DirectAccessTable: | ||
|
||
def __init__(self): | ||
self.T = [None]*1000 | ||
|
||
def direct_address_search(self, k): | ||
if len(self.T) > k: | ||
return self.T[k] | ||
return None | ||
|
||
def direct_address_insert(self, x): | ||
if len(self.T) < x.key: | ||
self.T = self.T + [None]*1000 # expand table | ||
self.T[x.key] = x | ||
|
||
def direct_address_delete(self, x): | ||
if len(self.T) < x.key: | ||
return | ||
self.T[x.key] = None | ||
|
||
def __str__(self): | ||
result = "PRINTING [" | ||
for node in range(len(self.T)): | ||
if node != None: | ||
result += str(self.T[node]) + ", " | ||
else: | ||
result += "None, " | ||
return result + "]" | ||
|
||
|
||
a = Node(2, [1,5,3,2]) | ||
b = Node(3, [2,3,69]) | ||
c = Node(10, [69,420]) | ||
|
||
dat = DirectAccessTable() | ||
|
||
dat.direct_address_insert(a) | ||
dat.direct_address_insert(b) | ||
print(str(dat)) | ||
dat.direct_address_insert(c) | ||
|
||
print(dat.direct_address_search(b.key)) | ||
dat.direct_address_delete(b) | ||
print(dat.direct_address_search(b.key)) | ||
print(str(dat)) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import Python.Datastrukturer.LinkedList as LL | ||
import random | ||
import math | ||
class HashTable: | ||
|
||
def __init__(self): | ||
self.T = [] | ||
for i in range(10): | ||
self.T.append(LL.LSingly()) | ||
|
||
def hash_search(self, k): | ||
hashKey = self.hash_function(k) | ||
if hashKey > len(self.T): | ||
return None | ||
return self.T[hashKey].list_search(k) | ||
|
||
def hash_insert(self, x): | ||
hashKey = self.hash_function(x.key) | ||
while len(self.T) < hashKey+1: # TODO: Use Table-insert instead of this (p 464) | ||
self.T.append(LL.LSingly()) | ||
self.T[hashKey].list_insert(x) | ||
|
||
def hash_delete(self, x): | ||
hashKey = self.hash_function(x.key) | ||
if len(self.T) < hashKey: | ||
return | ||
self.T[hashKey].list_delete(x) | ||
|
||
def hash_function(self, key): # TODO: Modify dis | ||
A = (math.sqrt(5) - 1)/2 | ||
m = 2**5 | ||
b = (key*A) % 1 | ||
return math.floor(m*b) | ||
|
||
def __str__(self): | ||
result = "[" | ||
for node in self.T: | ||
result += str(node) + "," | ||
result += "]\n Fordeling: [" | ||
for node in self.T: | ||
result += str(node.list_length()) + "," | ||
result += "]" | ||
return result | ||
|
||
|
||
|
||
|
||
for i in range(3000): # reliability testing | ||
ht = HashTable(); | ||
for j in range(1000): | ||
a = LL.Node(random.randint(0,100)) | ||
ht.hash_insert(a) | ||
|
||
print("\n\n" + str(ht)) | ||
|
||
ht.hash_delete(a) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
from Python.Datastrukturer.HeapList import HeapList as HL | ||
import random | ||
|
||
def exchange(A, idx_A, idx_B): | ||
temp = A[idx_A] | ||
A[idx_A] = A[idx_B] | ||
A[idx_B] = temp | ||
return A | ||
|
||
def parent(i): | ||
return i // 2 | ||
|
||
|
||
def left(i): | ||
return 2 * i | ||
|
||
|
||
def right(i): | ||
return (2 * i) + 1 | ||
|
||
def build_max_heap(A): # O(n*lg(n))) produces a max-heap from an unordered array | ||
for i in range(A.heapsize//2, -1, -1): # n/2 | ||
A = max_heapify(A, i) | ||
return A | ||
|
||
# Max heap property: A[parent(i)] >= A[i], largest element is the root | ||
# Min heap property: A[parent(i)] <= A[i], smallest element is the root | ||
# Height of a heap: θ(lg n) | ||
|
||
def max_heapify(A, idx): # O(lg n), helps maintain the max-heap property | ||
if A[0] is not None: | ||
A.addNone() | ||
idx += 1 | ||
leftIdx = left(idx) | ||
rightIdx = right(idx) | ||
largest = idx | ||
if leftIdx < A.heapsize and A[leftIdx] > A[largest]: # if the left child is larger than its parent | ||
largest = leftIdx | ||
if rightIdx < A.heapsize and A[rightIdx] > A[largest]: # if the right child is the largest | ||
largest = rightIdx | ||
if largest != idx: # if the parent is not the largest | ||
A = exchange(A, idx, largest) # Exchange the parent with the largest element | ||
A = max_heapify(A, largest) # Check if the element should be placed lower down | ||
if A[0] is None: | ||
A.removeNone() | ||
return A | ||
|
||
|
||
def heapsort(A): | ||
A = build_max_heap(A) # n lg(n) | ||
for i in range(len(A.getArr())-1,0,-1): # n | ||
A = exchange(A, 0, i) | ||
A.reduceHeapSize() | ||
A = max_heapify(A,0) # lg n | ||
return A | ||
|
||
arr = [1,1,2,6,39] | ||
heap = HL(arr, len(arr)) | ||
heap = build_max_heap(heap) | ||
#print(heap) | ||
|
||
for i in range(10): | ||
heap.addInFront(random.randint(-100,100)) | ||
heap = max_heapify(heap,0) | ||
|
||
#print(heap) | ||
|
||
arr = [3,2,6,19,2,3,-1,-53,2,4,5.34,-123] | ||
testHeap = HL(arr, len(arr)) | ||
print(heapsort(testHeap)) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
|
||
|
||
class HeapList: | ||
def __init__(self, arr, heapsize): | ||
self.arr = arr | ||
self.heapsize = heapsize | ||
|
||
def __str__(self): | ||
return str(self.arr) | ||
|
||
def __getitem__(self, item): | ||
return self.arr[item] | ||
|
||
def __setitem__(self, key, value): | ||
self.arr[key] = value | ||
|
||
def addNone(self): | ||
self.arr = [None] + self.arr | ||
self.heapsize += 1 | ||
|
||
def removeNone(self): | ||
self.arr = self.arr[1:] | ||
self.heapsize -= 1 | ||
|
||
def addInFront(self, value): | ||
self.arr = [value] + self.arr | ||
self.heapsize += 1 | ||
|
||
def reduceHeapSize(self): | ||
self.heapsize -= 1 | ||
|
||
def getArr(self): | ||
return self.arr |
Oops, something went wrong.