So I was trying to implement LCA using Euler tour and RMQ with Sparse Table in python. My code is working fine, if I insert number from left side of the tree. The code for building the tree is:
The node class has data, left_child and right_child:
class Node:
def __init__(self, value):
self.data = value
self.right_child = None
self.left_child = None
Then I have a tree class which I used to build the tree:
class Tree:
content = []
def __init__(self):
self.root = None
def add_child(self, arr, root, i, n):
if i < n:
temp = Node(arr[i])
root = temp
root.left_child = self.add_child(arr, root.left_child, 2 * i + 1, n)
root.right_child = self.add_child(arr, root.right_child, 2 * i + 2, n)
return root
def pre_order(self, root):
if root != None:
Tree.content.append(root.data)
self.pre_order(root.left_child)
self.pre_order(root.right_child)
return Tree.content
Finally, I got an LCA class which mainly contains the function for building the sparse table, then do a RMQ on the sparse table, then a function that does the part of the euler tour and finally the function for finding LCA.
class LCA:
def __init__(self, root, length):
self.pre_process_array = [[0] * (math.floor(math.log2(length) + 2)) for _ in range((length * 2) - 1)]
self.euler = [0] * (length * 2 - 1)
self.height = [0] * (length * 2 - 1)
self.index = [-1 for _ in range(length + 1)]
self.tour = 0
self.euler_tour(root, 0)
self.build_sparse_table(self.height)
print(self.pre_process_array)
def build_sparse_table(self, height_array):
for i in range(len(height_array)):
self.pre_process_array[i][0] = height_array[i]
j = 1
while (1 << j) <= len(height_array):
i = 0
while (i + (1 << j) - 1) < len(height_array):
if self.pre_process_array[i][j - 1] < self.pre_process_array[i + (1 << (j - 1))][j-1]:
self.pre_process_array[i][j] = self.pre_process_array[i][j - 1]
else:
self.pre_process_array[i][j] = self.pre_process_array[i + (1 << (j - 1))][j - 1]
i += 1
j += 1
def rmq(self, l, h):
j = int(math.log2(h - l + 1))
if self.pre_process_array[l][j] <= self.pre_process_array[h - (1 << j) + 1][j]:
return self.pre_process_array[l][j]
else:
return self.pre_process_array[h - (1 << j) + 1][j]
def euler_tour(self, root, level):
if root is not None:
self.euler[self.tour] = root.data
self.height[self.tour] = level
self.tour += 1
if self.index[root.data] == -1:
self.index[root.data] = self.tour - 1
if root.left_child is not None:
self.euler_tour(root.left_child, level + 1)
self.euler[self.tour] = root.data
self.height[self.tour] = level
self.tour += 1
if root.right_child is not None:
self.euler_tour(root.right_child, level + 1)
self.euler[self.tour] = root.data
self.height[self.tour] = level
self.tour += 1
def find_LCA(self, val1, val2):
if val1 >= len(self.index) or val2 >= len(self.index) or self.index[val1] == -1 or self.index[val2] == -1:
return -1
if self.index[val1] > self.index[val2]:
return self.euler[self.rmq(self.index[val2], self.index[val1])]
elif self.index[val2] > self.index[val1]:
return self.euler[self.rmq(self.index[val1], self.index[val2])]
And my driver code is as follow:
tree_data = [1,2,3,4,5,6,7,8,9]
length = len(tree_data)
tree = Tree()
root = tree.root
tree.root = tree.add_child(tree_data, root, 0, length)
l = LCA(tree.root, length)
print(l.find_LCA(6, 3))
so, my tree should something look like:
1
/ \
2 3
/ \ / \
4 5 6 7
/ \
8 9
Now, if I try to find the LCA(8, 9) or LCA(4, 3), I get the correct output but whenever I try to give LCA(6, 7) or LCA(3, 7), It always keeps returning 2 as the answer where it should return 3 and 3 respectively.
I don't have any idea where is the mistake as, from my side it looks pretty fine.
Related
I have tried to implement the Naive and Heap Dijkstra as shown below but somehow my naive Dijkstra implementation is surprisingly faster. I debugged my code but couldn't understand where my problem in my implementations are.
Why is my heap-based implementation is slower than the naive implementation?
Raw data is stored here:
https://www.algorithmsilluminated.org/datasets/problem9.8.txt
Data Import and Manipulation:
import time
with open("DijkstraTest2.txt", 'r') as input:
lines = input.readlines()
lengths = {}
vertices = []
for line in lines:
contents = line.split("\t")
vertices.append(contents[0])
for content in contents:
content = content.replace('\n', '')
if ',' in content:
edge = contents[0] + '-' + content.split(',')[0]
lengths[edge] = int(content.split(',')[1])
Naive Dijkstra:
def NaiveDijkstra(vertices, start_point, lengths):
X = [start_point]
shortest_paths = {}
for vertex in vertices:
if vertex == start_point:
shortest_paths[vertex] = 0
else:
shortest_paths[vertex] = 999999999999
subset = [key for key in lengths.keys() if start_point == key.split('-')[0]
and key.split('-')[0] in X and key.split('-')[1] not in X]
while len(subset) > 0:
temp_min_dict = {}
for edge in subset:
temp_min = shortest_paths[edge.split('-')[0]] + lengths[edge]
temp_min_dict[edge] = temp_min
new_edge = min(temp_min_dict, key=temp_min_dict.get)
X.append(new_edge.split('-')[1])
shortest_paths[new_edge.split('-')[1]] = shortest_paths[new_edge.split('-')[0]] + lengths[new_edge]
subset = []
for key in lengths.keys():
if key.split('-')[0] in X and key.split('-')[1] not in X:
subset.append(key)
return shortest_paths
start_time = time.time()
print(NaiveDijkstra(vertices = vertices, start_point = '1', lengths = lengths)['197'])
print(time.time() - start_time, "seconds")
My Heap based Dijkstra code:
class Heap:
def __init__(self):
self.size = 0
self.lst = []
def swap(self, a):
if self.size == 1:
return self.lst
else:
if a == 1:
i = 1
else:
i = a // 2
while i > 0:
if i * 2 - 1 >= self.size:
break
elif self.lst[i - 1][1] > self.lst[i * 2 - 1][1]:
temp = self.lst[i - 1]
self.lst[i - 1] = self.lst[i * 2 - 1]
self.lst[i * 2 - 1] = temp
elif i * 2 >= self.size:
break
elif self.lst[i - 1][1] > self.lst[i * 2][1]:
temp = self.lst[i - 1]
self.lst[i - 1] = self.lst[i * 2]
self.lst[i * 2] = temp
i -= 1
# print(f"output: {self.lst}")
def insert(self, element):
# print(f"input: {self.lst}")
self.lst.append(element)
self.size += 1
self.swap(self.size)
def extractmin(self):
val = self.lst.pop(0)[0]
self.size -= 1
self.swap(self.size - 1)
return val
def delete(self, deleted):
ix = self.lst.index(deleted)
temp = self.lst[-1]
self.lst[ix] = temp
self.lst[-1] = deleted
self.lst.pop(-1)
self.size -= 1
#self.swap(self.size)
def FastDijkstra(vertices, start_point, lengths):
X = []
h = Heap()
width = {}
shortest_paths = {}
for vertex in vertices:
if vertex == start_point:
width[vertex] = 0
h.insert((vertex, width[vertex]))
else:
width[vertex] = 999999999999
h.insert((vertex, width[vertex]))
while h.size > 0:
w = h.extractmin()
X.append(w)
shortest_paths[w] = width[w]
Y = set(vertices).difference(X)
for x in X:
for y in Y:
key = f"{x}-{y}"
if lengths.get(key) is not None:
h.delete((y, width[y]))
if width[y] > shortest_paths[x] + lengths[key]:
width[y] = shortest_paths[x] + lengths[key]
h.insert((y, width[y]))
return shortest_paths
start_time = time.time()
print(FastDijkstra(vertices=vertices, start_point='1', lengths=lengths)['197'])
print(time.time() - start_time, "seconds")
The way you implemented the heap version is not efficient. Notably the following make it inefficient:
All nodes are put on the heap instead of only the direct neighbors of the visited nodes. This makes the heap large and slower than needed.
Y = set(vertices).difference(X) is a slow operation, and makes Y unnecessary large.
The nested loop that tries every pair in the Cartesian product of X and Y to see if it is an edge. This point together with the previous should be replaced with a collection of edges starting from X, and then discarding edges that lead to already visited nodes.
For every found edge to delete the target node from the heap, and re-insert it, even if the width didn't change! Deletion is a costly operation (see next point). Only if the Heap implementation supports a decrease-key operation, this is an option, but otherwise the heap should just get an extra entry for the same vertex, knowing that the one with the lowest cost will come out of the heap first.
The heap's delete method has a bad time complexity due to the .index() call.
The heap's extractmin method has a bad time complexity, due to the .pop(0) call. This has O(n) time complexity.
The heap's extractmin does not give correct results (again due to that pop(0)). Here is a little script that shows a mistake:
h = Heap()
for value in 4, 3, 5, 2, 1:
h.insert((value, value))
print(h.extractmin()) # 1 = OK
print(h.extractmin()) # 2 = OK
print(h.extractmin()) # 4 = NOK. 3 expected.
The data structure lengths does not allow to quickly find the edges from a particular vertex. But this is a point that is also making the naive implementation slow. I would however suggest to turn that in a dict.
If this is done right it should run faster. Certainly when you would make use of the native heapq module you'll get good running times.
Here is a (much) faster implementation. It doesn't bother about unreachable vertices, and doesn't bother about possibly having multiple entries on the heap for the same node (with different distances). But it does start with only the starting node on the heap, and uses heapq:
from heapq import heappush, heappop
from collections import defaultdict
def FastDijkstra(vertices, start_point, lengths):
# Create a dictionary for the edges, keyed by source node
edges = defaultdict(list)
for key, length in lengths.items():
x, y = key.split("-")
edges[x].append((length, y))
heap = [(0, start_point)]
shortest_paths = {}
while heap:
cost, x = heappop(heap)
if x in shortest_paths:
continue # this vertex had already been on the heap before
shortest_paths[x] = cost
for length, y in edges[x]:
if y not in shortest_paths:
heappush(heap, (cost + length, y))
return shortest_paths
In my tests this ran hundreds times faster.
Thanks to the above answer (wonderful analysis) I adjusted my implementation which is way faster than the previous version. It is shown below.
class Heap:
def __init__(self):
self.size = 0
self.lst = []
def swap(self, a):
if self.size == 1:
return self.lst
else:
if a == 1:
i = 1
else:
i = a // 2
while i > 0:
if i * 2 - 1 >= self.size:
break
elif self.lst[i - 1][1] > self.lst[i * 2 - 1][1]:
temp = self.lst[i - 1]
self.lst[i - 1] = self.lst[i * 2 - 1]
self.lst[i * 2 - 1] = temp
elif i * 2 >= self.size:
break
elif self.lst[i - 1][1] > self.lst[i * 2][1]:
temp = self.lst[i - 1]
self.lst[i - 1] = self.lst[i * 2]
self.lst[i * 2] = temp
elif self.lst[2*i - 1][1] > self.lst[i * 2][1]:
temp = self.lst[2*i - 1]
self.lst[2*i - 1] = self.lst[i * 2]
self.lst[i * 2] = temp
i -= 1
#print(f"output: {self.lst}")
def insert(self, element):
#print(f"input: {self.lst}")
self.lst.append(element)
self.size += 1
self.swap(self.size)
def extractmin(self):
val = self.lst[0][0]
del self.lst[0]
self.size -= 1
self.swap(self.size-1)
return val
def delete(self, deleted):
ix = self.lst.index(deleted)
temp = self.lst[-1]
self.lst[ix] = temp
self.lst[-1] = deleted
del self.lst[-1]
self.size -= 1
#self.swap(self.size)
def FastDijkstra(vertices, start_point, lengths):
X = []
h = Heap()
width = {}
shortest_paths = {}
for vertex in vertices:
if vertex == start_point:
width[vertex] = 0
h.insert((vertex, width[vertex]))
else:
width[vertex] = 999999999999
h.insert((vertex, width[vertex]))
while h.size > 0:
w = h.extractmin()
X.append(w)
shortest_paths[w] = width[w]
Y = set(vertices).difference(X)
for y in Y:
key = f"{w}-{y}"
if lengths.get(key) is not None:
h.delete((y, width[y]))
if width[y] > shortest_paths[w] + lengths[key]:
width[y] = shortest_paths[w] + lengths[key]
h.insert((y, width[y]))
return shortest_paths
start_time = time.time()
print(FastDijkstra(vertices=vertices, start_point='1', lengths=lengths)['197'])
print(time.time() - start_time, "seconds")
data = input("Input:")
def parse_to_int(dat): # parse input data to int list
individuals = dat.split(" ")
num = []
for individual in individuals:
num.append((int)(individual))
return num
def get_Max_and_MaxIndex_MinIndex(num_list): # get maximul value, its index and minimum value
sign = 1
val = 0
max_val = 0
min_val = 0
max_ind = 0
count = 0
for num in num_list:
count += 1
val = val + sign * num
sign = -1 * sign
if (max_val < val):
max_val = val
max_ind = count
if (min_val > val):
min_val = val
return max_val, max_ind, min_val
def sub_sum(ind): # calculate subsum until ind
global num_input
global subsum
subsum = 0
for i in range(ind + 1):
subsum += num_input[i]
return subsum
def sub_sum_with_sign(ind): # calculate subsum with sign until ind
global num_input
global subsum_withsign
subsum_withsign = 0
sign = 1
for i in range(ind + 1):
subsum_withsign += sign * num_input[i]
sign = -1 * sign
return subsum_withsign
def fill_data(ind): # fill data for print in empty data
global print_data
global cur_x
global cur_y
if ind % 2 == 0:
str = '/'
dx = 1
dy = 1
else:
str = '\\'
dx = 1
dy = -1
for _ in range(num_input[ind]):
print_data[cur_y][cur_x] = str
cur_x += dx
cur_y += dy
if ind % 2 == 0:
cur_y -= 1
else:
cur_y += 1
return print_data
# main program
num_input = parse_to_int(data)
col_num = 0 # column count
for elem in num_input:
col_num += elem
max_min_num = get_Max_and_MaxIndex_MinIndex(num_input)
row_num = max_min_num[0] - max_min_num[2] # row count
start_num = 0
for i in range(max_min_num[1]):
start_num += num_input[i] # maximum height element number
subsum = 0
subsum_withsign = 0
cur_x = 0
cur_y = -1 * max_min_num[2]
# start output
print("Output:\n")
print(" " * start_num + "o" + " " * (col_num - start_num))
print(" " * (start_num - 1) + "/|\\" + " " * (col_num - start_num - 1))
print(" " * (start_num - 1) + "< >" + " " * (col_num - start_num - 1))
# prepare data for print
print_data = []
for i in range(row_num):
print_data.append([])
for j in range(col_num):
print_data[i].append(" ")
for ind in range(len(num_input)):
fill_data(ind)
# print data
for indr in range(row_num - 1, -1, -1):
print("".join(print_data[indr]))
The above code will give this Output
In this code, a graph is generated using python without using any libraries. The Highest tip of the graph is marked.
I want to mark the lowest tip of the graph as shown in the image below. I completely have no idea about this one. which values should be changed in order to mark the lowest tip in the generated graph?
I am a newbie to stackoverflow, please comment if you need more clarity with this..
How to mark the lowest tip here Please Help me with this
This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 4 years ago.
I have a Class called Heap. In it i have declared three separate lists (min_list, max_list and xor_list). When build_heap is called, it creates a heap list over some inital input list. I then set all three lists (min,max and xor) to the heap list. So they shouldn't be linked in any way. But when I do something like
self.min_list[2] = "6"
it changes all of the three lists. My code is below:
class Heap:
def __init__(self):
self.heap_list = [None]
self.currentSize = 0
self.alist = []
self.min_list = []
self.max_list = []
self.xor_list = []
self.i = 0
self.list_start = 0
self.SCA = 0
self.interval_to = 0 # interval in initial list, not in heap numbering
self.interval_from = 0
def build_heap(self, alist):
i = 0
self.alist = alist
while len(alist) > (2**i):
i += 1
self.i = i
self.list_start = (2**self.i)
for j in range(len(alist)):
self.heap_list.insert(self.list_start + j, alist[j])
for k in range((2**self.i)-1):
self.heap_list.insert(k, None)
# append None to list
# print(len(alist))
for l in range((2**self.i)-len(alist)):
# print("lol")
self.heap_list.append(None)
tup_list = self.heap_list
self.min_list = tup_list
self.max_list = tup_list
self.xor_list = tup_list
def smallest_common_ancestor(self):
bin_from = list(bin(int(self.interval_from) + int(self.list_start))[2:])
bin_to = list(bin(int(self.interval_to) + int(self.list_start))[2:])
smallest_common_ancestor = ""
p = 0
while len(bin_to) > p:
if bin_to[p] == bin_from[p]:
print(p)
smallest_common_ancestor = smallest_common_ancestor + str(bin_to[p])
p += 1
self.SCA = int(smallest_common_ancestor, 2)
def low_id(self):
print("Min_list before change: {}".format(self.min_list))
int_from = int(self.interval_from) + int(self.list_start)
int_to = int(self.interval_to) + int(self.list_start)
m = int_to // 2
while m + 1 != self.SCA:
if (m * 2) == int_to:
self.min_list[m] = self.min_list[(m * 2)]
elif ((m*2) + 1) == int_from:
self.min_list[m] = self.min_list[(m * 2) + 1]
elif self.min_list[m * 2] is None:
if self.min_list[(m * 2) + 1] is None:
self.min_list[m] = None
else:
self.min_list = self.min_list[(m * 2) + 1]
elif self.min_list[(m * 2) + 1] is None:
self.min_list[m] = self.min_list[m * 2]
elif int(self.min_list[m * 2]) >= int(self.min_list[(m * 2) + 1]):
self.min_list[m] = self.min_list[(m * 2) + 1]
else:
self.min_list[m] = self.min_list[(m * 2)]
m -= 1
return self.min_list[self.SCA]
At the beginning i do something along these lines, it shouldn't be the part of the problem
heap = Heap()
heap.build_heap(input_list)
heap.interval_to, heap.interval_from = f.readline.split()
def build_heap(self, alist):
# ...
tup_list = self.heap_list
self.min_list = tup_list
self.max_list = tup_list
self.xor_list = tup_list
This is where your class "links" the lists. Python is pass-by-reference, so min_list, max_list, xor_list, tup_list and heap_list will all point to the same object after you've called build_heap().
To create independent lists with the same values, you need to explicitly copy them:
new_list = list(old_list)
Below is what I have done but it Does not handle the max requirement on insert.
how do I Give the class a max value and check it in the insert and then remove the least significant element. Then figure out what is the least significant element in the implementation.
Having some issues trying to figure this out.
import math
import random
class BinaryHeap:
def __init__(self, array, direction=1, size=100):
if(size > len(array)):
self.size = len(array)
else:
self.size = size;
self.bBinaryHeap = array[:]
if 0 < direction:
self.compare = self.greater
else:
self.compare = self.less
self.buildBinaryHeap()
def node(self, index):
return (index << 1) + 1
def parent(self, index):
return (index - 1) >> 1
def bBinaryHeapifyDown(self, index):
swap = self.bBinaryHeap[index]
while self.node(index) < self.size:
node = self.node(index)
if node + 1 < self.size and self.compare(self.bBinaryHeap[node], self.bBinaryHeap[node + 1]) > 0:
node += 1
if self.compare(swap, self.bBinaryHeap[node]) > 0:
self.bBinaryHeap[index] = self.bBinaryHeap[node];
else:
break
index = node
self.bBinaryHeap[index] = swap
def upheapify(self, index):
while 0 < index and self.compare(self.bBinaryHeap[index], self.bBinaryHeap[self.parent(index)]) < 0:
parent = self.parent(index)
swap = self.bBinaryHeap[parent]
self.bBinaryHeap[parent] = self.bBinaryHeap[index]
self.bBinaryHeap[index] = swap
index = parent
def buildBinaryHeap(self):
indices = range(0, int(self.size / 2))
reversed(indices)
for index in indices:
self.bBinaryHeapifyDown(index)
def insert(self, value):
self.shrink()
index = self.size
self.bBinaryHeap[index] = value
self.size += 1
self.upheapify(index)
def search(self, value):
for index in range(self.size):
if self.bBinaryHeap[index] == value:
return index
def delete(self, value):
index = self.search(value)
self.size -= 1
self.bBinaryHeap[index] = self.bBinaryHeap[self.size]
parent = self.parent(index)
if (index == 0) or (self.compare(self.bBinaryHeap[parent], self.bBinaryHeap[index]) < 0):
self.bBinaryHeapifyDown(index)
else:
self.upheapify(index)
def shrink(self):
capacity = len(self.bBinaryHeap)
if capacity == self.size:
self.bBinaryHeap.extend([0] * capacity)
def greater(self, value1, value2):
if value1 == value2:
return 0
elif value1 < value2:
return 1
elif value1 > value2:
return -1
def less(self, value1, value2):
if value1 == value2:
return 0
elif value1 < value2:
return -1
elif value1 > value2:
return 1
def getLevel(self, index):
return int(math.floor(math.log(index + 1, 2)))
def displayBinaryHeap(self):
printBinaryHeap = str(self.bBinaryHeap)
height = self.getLevel(self.size)
previous = -1
for index in range(self.size):
getLevel = self.getLevel(index)
n = height - getLevel
indent = int(math.pow(2, n + 1) - 2)
spacing = 2 * indent
if getLevel != previous:
printBinaryHeap += '\n'
printBinaryHeap += ' ' * indent
previous = getLevel
else:
printBinaryHeap += ' ' * spacing
printBinaryHeap += '%4d' % self.bBinaryHeap[index]
print(printBinaryHeap)
if __name__ == "__main__":
size =10
array = [random.randint(0, 100) for i in range(size)]
bBinaryHeap = BinaryHeap(array, 1, 100)
print('Binary bBinaryHeap:')
bBinaryHeap.displayBinaryHeap()
Your code has numerous indentation errors. In python, indentation counts.
As for this code:
if 0 < direction:
self.compare = self.greater
else:
self.compare = self.less
self.greater and self.less don't exist. You are doing the equivalent of this:
x = elephant
That's nice, but unless you've set the variable elephant to some value prior to that line, that is an error.
how do I Give the class a max value
class BinaryHeap:
pass
BinaryHeap.max = 10
print(BinaryHeap.max)
--output:--
10
and check it in the insert
class BinaryHeap:
max = 10
def insert(self):
print(self.max)
bh = BinaryHeap()
bh.insert()
--output:--
10
then remove the least significant element
x = 0b1111
print(x) #15
y = x >> 1
print("{:b}".format(y)) #111
print(y) #7
Then figure out what is the least significant element in the implementation
x = 0b1110
print(x) #=>14
b_str = "{:b}".format(x)
print(repr(b_str)) #=> '1110'
for direction in [1, -1]:
if direction > 0:
least_signif = b_str[-1]
else:
least_signif = b_str[0]
print(least_signif)
--output:--
0
1
The purpose of this code is to create the shortest path that connect each point. I've tried to implement the Kruskals algorithm in Python, but there is a problem and it occurs when the function findSet(x) is called. It seems like the program enters a infinite loop. I've tried to print x, x.dad and x.dad.dad and x in the crucial moment returns the initial x. I really don't know where is the problem.
class Point:
def __init__(self,x = None, y = None):
self.x = x
self.y = y
self.dad = None
self.rank = None
class Edge:
def __init__(self, firstPoint = None, secondPoint = None, value = None):
self.firstPoint = firstPoint
self.secondPoint = secondPoint
if self.firstPoint != None and self.secondPoint != None:
self.value = abs(firstPoint.x-secondPoint.x) + abs(firstPoint.y - secondPoint.y)
else:
self.value = float("inf")
def makeSet(node):
node.dad = node
node.rank = 0
def findSet(x):
print x, x.dad,x.dad.dad
if x == x.dad:
return x
x.dad = findSet(x.dad)
return x.dad
def unionSet(node1,node2):
root1 = findSet(node1)
root2 = findSet(node2)
if root1.rank < root2.rank:
root1.dad = root2
if root1.rank > root2.rank:
root2.dad = root1
else:
root2.dad = root1
root1.rank += 1
def merge(A, p, q, r):
L = A[p:q+1]
R = A[q+1:r+1]
infinite = Edge()
L.append(infinite)
R.append(infinite)
temp = []
i = 0
j = 0
for k in range(p,r+1):
if L[i].value <= R[j].value:
temp.append(L[i])
i += 1
else:
temp.append(R[j])
j += 1
A[p:r+1] = temp
def mergeSort(A,p,r):
A2 = A
if p < r:
q = int((p+r)/2)
mergeSort(A2, p, q)
mergeSort(A2, q+1, r)
merge(A2, p, q, r)
def readPoint(A):
temp = []
for i in range(0,len(A), 2):
tempPoint = Point(A[i],A[i+1])
makeSet(tempPoint)
temp.append(tempPoint)
return temp
def calculateEdges(A):
tempArray = []
for i in range(0,len(A)):
for j in range(i+1,len(A)):
edge = Edge(A[i], A[j])
tempArray.append(edge)
return tempArray
def Kruskal(N, E):
mergeSort(E,0,len(E)-1)
j = 0
i = 0
total = 0
while j < N:
if findSet(E[i].firstPoint) != findSet(E[i].secondPoint):
unionSet(E[i].firstPoint,E[i].secondPoint)
j += 1
total += E[i].value
if i < len(E) - 1:
i += 1
return total
Ar = readPoint([18, 2, 99, 68])
E = calculateEdges(Ar)
print Kruskal(len(Ar),E)