Hello I have this code and I don't know how to count how many exchanges it does :(
def quicksort(lista,izq,der):
i = izq
j = der
pivote = lista[(izq + der)//2]
while i <= j:
while lista[i] < pivote:
i += 1
while pivote < lista[j]:
j -= 1
if i <= j:
aux = lista[i]
lista[i] = lista[j]
lista[j] = aux
i += 1
j -= 1
if izq < j:
quicksort(lista, izq, j);
if i < der:
quicksort(lista, i, der);
So where can I put a counter that says me how many exchanges It does?
Edit: I need that the function returns me that number and how many comparisons It does.
def quicksort(lista,izq,der):
i = izq
j = der
pivote = lista[(izq + der)//2]
swap_count = 0
while i <= j:
while lista[i] < pivote:
i += 1
while pivote < lista[j]:
j -= 1
if i <= j:
aux = lista[i]
lista[i] = lista[j]
lista[j] = aux
swap_count += 1
i += 1
j -= 1
if izq < j:
swap_count += quicksort(lista, izq, j)
if i < der:
swap_count += quicksort(lista, i, der)
return swap_count
Here's what I would do, if I'm understanding you right.
def quicksort(lista,izq,der):
i = izq
j = der
swap_count = 0
compare_count = 0
pivote = lista[(izq + der)//2]
while i <= j:
while lista[i] < pivote:
i += 1
while pivote < lista[j]:
j -= 1
if i <= j:
aux = lista[i]
lista[i] = lista[j]
lista[j] = aux
swap_count += 1
i += 1
j -= 1
compare_count += 1
if izq < j:
other_swap, other_compare = quicksort(lista, izq, j)
swap_count += other_swap
compare_count += other_compare
if i < der:
other_swap, other_compare = quicksort(lista, i, der)
swap_count += other_swap
compare_count += other_compare
return (swap_count, compare_count)
This way you add in the swaps and the compares of the recursive calls as you make them.
Related
Somebody please help me find the maximum (longest) connected component (not diagonally, only bottom, top, left and right) in a matrix. My code does not work, I have been tying to solve this problem for 24 hours.
For first version:
What's idea? For example, take one element with value '1' and change its value to '2' and look for the other '1' around. Change their ('1' around) value to 3. Take one elem with value '3', look for '1' around, change '1' to '4', etc. All elements > 1 are calculated (l) and compared with the intermediate value of the largest component (comps[u], comps[1] for initial '1').
import random
n = int(input())
m = int(input())
#create and output matrix with elems 1-4
a = [[0]*(m+2) for i in range(n+2)]
b = [[0]*(m+2) for i in range(n+2)]
for i in range(n+2):
for j in range(m+2):
if i == 0 or i == n+1 or j == 0 or j == m+1:
a[i][j] = -100
for i in range(1, n+1):
for j in range(1, m+1):
s = random.randint(1, 4)
a[i][j] = s
for i in range(1, n+1):
for j in range(1, m+1):
print(a[i][j], end = " ")
print()
comps = [0]*5 #counter of longest components
u = 1 #it is value of the elem, adjacent elems whith which we well check
def main(u):
if u == 5: return()
global a
global b
k = 0
l = 0
global m
global n
global comps
for i in range(1, n+1):
for j in range(1, m+1):
if a[i][j] == u and k == 0:
b[i][j] = 2
k+=1
elif a[i][j] == u:
b[i][j] = 1
k+=1
w = m//2
v = n//2
#a[v][w] = u
#b[v][w] = 2
p = True
c = 2
while p:
for h in range(1, n+1):
for hh in range(1, m+1):
if b[h][hh] == c and b[h-1][hh] == 1:
b[h-1][hh] = c+1
c += 1
if b[h][hh] == c and b[h+1][hh] == 1:
b[h+1][hh] = c+1
c += 1
if b[h][hh] == c and b[h][hh-1] == 1:
b[h][hh-1] = c+1
c += 1
if b[h][hh] == c and b[h][hh+1] == 1:
b[h][hh+1] = c+1
c += 1
else:
b[h][hh] = 2
if c not in b:
p = False
break
for x in range(1, n+1):
for y in range(1, m+1):
if b[x][y] > 1:
l += 1
b[x][y] = 0
a[x][y] = 0
if l > comps[u]:comps[u] = l
if k == l:
u+=1
main(u)
main(u)
maxk = max(comps)
for i in range(1,5):
if comps[i] == maxk:
print('The length of the longest con. comp. for digit ', i, ' is ', comps[i])
And second version with recursion, it's does not work either.
import random
n = int(input())
m = int(input())
a = [[0]*(m+2) for i in range(n+2)]
b = [[0]*(m+2) for i in range(n+2)]
def deep_find(q, o):
global b
global ww
ww += 1
t = q
d = o
b[t][d] = 0
if t <= n and b[t+1][d] == 1:
deep_find(t+1, d)
if t >= 1 and b[t-1][d] == 1:
deep_find(t-1, d)
if d<= m and b[t][d+1] == 1:
deep_find(t, d+1)
if d>= 1 and b[t][d-1] == 1:
deep_find(t, d-1)
print(ww)
return()
for i in range(n+2):
for j in range(m+2):
if i == 0 or i == n+1 or j == 0 or j == m+1:
a[i][j] = -100
for i in range(1, n+1):
for j in range(1, m+1):
s = random.randint(1, 4)
a[i][j] = s
for i in range(1, n+1):
for j in range(1, m+1):
print(a[i][j], end = " ")
print()
comps = [0]*5
u = 1
while u!=5:
k = 0
for i in range(1, n+1):
for j in range(1, m+1):
if a[i][j] == u:
b[i][j] = 1
k+=1
p = True
while p:
for i in range(1, n+1):
for j in range(1, m+1):
if b[i][j] == 1:
t = i
d = j
ww = 0
deep_find(t, d)
p = False
break
if ww>comps[u]: comps[u] = ww
if ww == k: u += 1
maxk = max(comps)
for i in range(1,5):
if comps[i] == maxk:
print( i, comps[i])
I have implemented some sorting algorithms including Insertion, Selection, Shell, two kinds of Merge. I found that the performance of my implements didn't accord with the description of Algorithms(4th).
For example, here are two kinds of Merge sorting. When sorting a list contains 100,000 elements, Merge1 takes about 0.6s, and Merge2 takes about 50+s. But Merge2 is almost the same as the one in Algorithms(4th) except I use python. I can't figure it out why Merge2 is so slow and how to improve it. Can somebody help me? Thanks!
class Merge1:
def merge(self, a, b):
i = 0; j = 0
res = []
while i < len(a) and j < len(b):
if a[i] < b[j]:
res.append(a[i])
i = i + 1
else:
res.append(b[j])
j = j + 1
res = res + a[i:] + b[j:]
return res
def sort(self, source):
if len(source) <= 1:
return source
half = len(source) // 2
left = self.sort(source[:half])
right = self.sort(source[half:])
retval = self.merge(left, right)
return retval
def is_sort(self, source):
length = len(source)
for i in range(0, length-1):
if source[i] > source[i+1]:
return False
return True
class Merge2:
def merge(self, source, lo, mid ,hi):
i = lo
j = mid + 1
aux = source[:]
k = lo
while k <= hi:
if i > mid:
source[k] = aux[j]
j = j + 1
elif j > hi:
source[k] = aux[i]
i = i + 1
elif aux[i] < aux[j]:
source[k] = aux[i]
i = i + 1
else:
source[k] = aux[j]
j = j + 1
k = k+1
def sort(self, source):
sz = 1
N = len(source)
while sz < N:
for lo in range(0, N-sz, sz+sz):
# pdb.set_trace()
self.merge(source, lo, lo+sz-1, min(lo+sz+sz-1, N-1))
sz = sz + sz
def is_sort(self, source):
length = len(source)
for i in range(0, length-1):
if source[i] > source[i+1]:
return False
return True
Here is the implement in Algorithms:
Here is the test code:
merge1 = Merge1()
source = np.random.randint(100000, size=100000).tolist()
start = time.time()
merge1.sort(source)
end = time.time()
print("Merge1 takes: {}s".format(end-start))
merge2 = Merge2()
source = np.random.randint(100000, size=100000).tolist()
start = time.time()
merge2.sort(source)
end = time.time()
print("Merge2 takes: {}s".format(end-start))
result:
E:>python sort.py
Merge1 takes: 0.6376256942749023s
Merge2 takes: 57.99568271636963s
Consider this modification. According to my quick tests, it improved the performance considerably (from nearly one minute down to less than 1 second). The main performance gain comes from avoiding to create that many copies of the whole list. The other alterations only increase performance marginally.
According to a simple comparison of the sum it should not mess up the list, but you should do some more tests if you like to use it.
class Merge4:
def merge(self, source, aux, lo, mid ,hi):
i = lo
j = mid + 1
a_j= aux[j]
a_i= aux[i]
k = lo
while k <= hi:
if i > mid:
source[k] = a_j
j += 1
a_j= aux[j]
elif j > hi:
source[k] = a_i
i += 1
a_i= aux[i]
elif a_i < a_j:
source[k] = a_i
i += 1
a_i= aux[i]
else:
source[k] = a_j
j += 1
a_j= aux[j]
k += 1
# update the aux array for the next call
aux[lo:hi+1]= source[lo:hi+1]
def sort(self, source):
sz = 1
N = len(source)
while sz < N:
sz_2= sz * 2
# create the aux array, that will be maintained continuously
# and add one extra None, so the "prefetching" works also
# during the last iteration (refering to a_i and a_j)
aux= source[:]
aux.append(None)
for lo in range(0, N-sz, sz_2):
# pdb.set_trace()
self.merge(source, aux, lo, lo+sz-1, min(lo+sz_2-1, N-1))
sz = sz_2
def is_sort(self, source):
length = len(source)
for i in range(0, length-1):
if source[i] > source[i+1]:
return False
return True
I tried to implement merge-sort in Python. Somehow this piece of code runs correctly (and pretty fast), but I don't know why: There is no return-statement in mergeSort()
from sys import stdin
def mergeSort(A):
if len(A) > 1:
m = int(len(A)/2)
L = A[:m]
R = A[m:]
mergeSort(L)
mergeSort(R)
l = 0
r = 0
a = 0
while l < len(L) and r < len(R):
if L[l] < R[r]:
A[a] = L[l]
l += 1
else:
A[a] = R[r]
r += 1
a += 1
while l < len(L):
A[a] = L[l]
l += 1
a += 1
while r < len(R):
A[a] = R[r]
r += 1
a += 1
def main():
A = []
for line in stdin:
A.append(int(line))
mergeSort(A)
print(A)
if __name__ == "__main__":
main()
def merge(l1,l2):
(lmerged,i,j) = ([],0,0)
while i+j < len(l1) + len(l2):
if i == len(l1):
lmerged.append(l2[j])
j = j+1
elif j == len(l2):
lmerged.append(l1[i])
i = i+1
elif l1[i] < l2[j]:
lmerged.append(l1[i])
i = i+1
elif l2[j] < l1[i]:
lmerged.append(l2[j])
j = j+1
else:
lmerged.append(l1[i])
i = i+1
j = j+1
return(lmerged)
def mergesort(l):
if len(l) < 2:
return(l)
else:
n = len(l)
leftsorted = mergesort(l[:n//2])
rightsorted = mergesort(l[n//2:])
return(merge(leftsorted,rightsorted))
What is the error in this code sample? On which list will this implementation fail? Is the logic correct or there is some flaw in my logic itself?
fail test: [1, 1] is sorted as [1]
fix: remove j = j + 1 in merge function in the last else block.
Below is my Merge function which is suppose to resemble what is shown in CLRS on page 31. For now I have commented out the code which would handle any remaining list items.
If I pass A = [1, 2, 1, 12, 2, 5] as input. The output is [1, 2, 1, None, None, None].
Can anyone shred some light on what I'm doing wrong?
def Merge(left, right):
result = [None] * (len(left) + len(right))
i, j, k = 0, 0, 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
result[k] = left[i]
#result.append(left[i])
i += 1
else:
result[k] = right[j]
#result.append(right[j])
j += 1
k += 1
## remaining items in remaining list
## while i < len(left):
## result[k] = left[i]
## i += 1; k+= 1;
##
## while j < len(right):
## result[k] = right[j]
## j += 1; k+= 1;
##
return result
## Ref.: CLRS page 34
def MergeSort(A):
if len(A) > 1:
mid = int(len(A)/2)
left = A[:mid]
right = A[mid:]
MergeSort(left)
MergeSort(right)
return Merge(left, right)
else:
return A
if __name__ == "__main__":
a = [1, 2, 1, 12, 2, 5]
print "a = %s" % a
print "sort a = %s" % MergeSort(a)
When calling MergeSort you are recursively returning new lists but, are never assigning them:
def Merge(left, right):
result = [None] * (len(left) + len(right))
i, j, k = 0, 0, 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
result[k] = left[i]
#result.append(left[i])
i += 1
else:
result[k] = right[j]
#result.append(right[j])
j += 1
k += 1
## remaining items in remaining list
## while i < len(left):
## result[k] = left[i]
## i += 1; k+= 1;
##
## while j < len(right):
## result[k] = right[j]
## j += 1; k+= 1;
##
return result
## Ref.: CLRS page 34
def MergeSort(A):
if len(A) > 1:
mid = int(len(A)/2)
left = A[:mid]
right = A[mid:]
#MergeSort(left)
# here should be
left = MergeSort(left)
#MergeSort(right)
# here should be
right = MergeSort(right)
return Merge(left, right)
else:
return A
if __name__ == "__main__":
a = [1, 2, 1, 12, 2, 5]
print "a = %s" % a
print "sort a = %s" % MergeSort(a)