Comparison of sorting algorithms - Page 1
Forum section: electronics / general

author: Picuino
author_rank: Super Contributor
timestamp: July 23, 2022, 05:36:33 pm
content: I have programmed a Python code to compare the performance of different data sorting algorithms.In each sorting method, I count the number of times a comparison is made between data and the number of times a copy or movement of data is made.Sometimes the data will be easy to compare (in the case for example of comparing integers as in this program), but there will be other times when you want to minimize the number of these operations because the data is complex to compare.The same thing happens with data movement or copying. If the movement or swap between two data is performed with the pointers pointing to those data, the operation will be fast. If, on the other hand, it is necessary to physically move the data and the data is large, we will want to minimize the number of data moved.For this reason, these data appear as the main performance indicators of each of the sorting algorithms.The execution time in seconds also appears at the end of the report, but this time must be interpreted relatively, because the algorithms are not optimized. They are running in Python and perform other operations such as counting the number of comparisons and data movements.This is the program:Code: (Python)"""Comparison between sorting algorithmsCopyright (c) 2022 PicuinoPermission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in allcopies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THESOFTWARE."""import copyimport mathimport randomimport timenum_compare = 0num_copy = 0def main():algorithms = [{"name":"Bubble Sort", "function":bubble_sort},{"name":"Direct Selection", "function":direct_selection},{"name":"Direct Insertion", "function":direct_insertion},{"name":"Binary Insertion", "function":binary_insertion},{"name":"ShellSort", "function":shellsort},{"name":"MergeSort", "function":mergesort},{"name":"HeapSort", "function":heapsort},{"name":"QuickSort", "function":quicksort},]algorithms_not_used = []# Initialize report filereport_head = "Algorithm,Array size,Comparisons,Units,Copies,Units,Execution time"with open("Report.csv", "wt") as report_file:report_file.write(report_head + '\n')print(report_head)# Sort arrays of different sizesarray_sizes = [10, 100, 1000, 10000, 100000, 1000000]for array_size in array_sizes:array = generate_random_array(array_size)for algorithm in algorithms:if array_size > 10000 and algorithm["function"] in (bubble_sort, direct_insertion, binary_insertion, direct_selection):continuereport = sort(algorithm, array)print(report)report_file.write(report + '\n')def sort(algorithm, array):global num_compare, num_copyarray_copy = copy.copy(array)num_compare = num_copy = 0run_time = time.time()algorithm["function"](array_copy)run_time = time.time() - run_timeif is_sorted(array_copy):report = generate_report(algorithm, len(array), num_compare, num_copy, run_time)else:report = "Array not sorted."return reportdef generate_random_array(array_size):array = []for i in range(array_size):array.append(random.getrandbits(32))return arraydef is_sorted(array):for i in range(1, len(array)):if array[i-1] > array:return Falsereturn Truedef generate_report(algorithm, array_size, num_compare, num_copy, run_time):report = []report.append("%-16s" % algorithm["name"])report.append("%d" % array_size)# Number of comparisonsif algorithm['function'] in (shellsort, heapsort, quicksort, mergesort):report.append("%1.4f,N*Ln(N)" % (num_compare/(array_size * math.log(array_size))))else:report.append("%1.4f,N*N" % (num_compare/float(array_size * array_size)))# Number of copiesif algorithm['function'] in (shellsort, heapsort, quicksort, mergesort):report.append("%1.4f,N*Ln(N)" % (num_copy/(array_size * math.log(array_size))))else:report.append("%1.4f,N*N" % (num_copy/float(array_size * array_size)))# Execution timereport.append("%1.4f" % run_time)return ','.join(report)def bubble_sort(array):global num_compare, num_copyfor i in range(len(array), 1, -1):moves = 0for j in range(1, i):num_compare += 1if array[j - 1] > array:num_copy += 3temp = arrayarray = array[j - 1]array[j -1] = tempmoves = 1if moves == 0:breakdef binary_insertion(array):global num_compare, num_copyfor pos in range(1, len(array)):num_copy += 1temp = arrayinf = 0sup = poswhile inf < sup:med = int((inf + sup) / 2)num_compare += 1if temp > array:inf = med + 1else:sup = medwhile pos > inf:num_copy += 1array = array[pos - 1]pos -= 1num_copy += 1array = tempreturn num_compare, num_copydef direct_selection(array):global num_compare, num_copyt_inf = 0t_sup = len(array) - 1while t_inf < t_sup:p_min = t_infj = t_inf + 1while j <= t_sup:num_compare += 1if array < array:p_min = jj += 1num_copy += 3temp = arrayarray = arrayarray = tempt_inf += 1def direct_insertion(array):global num_compare, num_copyi = 1while i < len(array):num_copy += 1temp = arrayj = iwhile j >= 1:num_compare += 1num_copy += 1if array[j - 1] > temp:array = array[j - 1]j -= 1else:breakarray = tempi += 1def shellsort(array):global num_compare, num_copyi = len(array)step = 1while i >= 4:i //= 2step *= 2while step >= 1:i = stepwhile i < len(array):num_copy += 1temp = arrayj = iwhile j >= step:num_compare += 1num_copy += 1if array[j-step] > temp:array = array[j-step]j -= stepelse:breakarray = tempi += 1step //= 2def heapsort(array):global num_compare, num_copy# Make heap structurepointer = int((len(array) - 1) / 2)while pointer >= 0:heapsort_screen(array, pointer, len(array) - 1)pointer -= 1# Sort arraypointer = len(array) - 1while pointer > 0:num_copy += 3temp = arrayarray = arrayarray = temppointer -= 1heapsort_screen(array, 0, pointer)def heapsort_screen(array, array_min, array_max):global num_compare, num_copydown = array_min * 2 + 1if (down > array_max):returnnum_copy += 1temp = arraywhile down <= array_max:if down < array_max:num_compare += 1if array[down + 1] > array:down += 1num_compare += 1if temp > array:breaknum_copy += 1array = arrayarray_min = downdown = down * 2 + 1num_copy += 1array = tempdef mergesort(array):mergesort_2(array, 0, len(array)-1)def mergesort_2(array, inicio, fin):global num_compare, num_copyif fin <= inicio+1:num_compare += 1if array<array:num_copy += 3temp = arrayarray = arrayarray = tempreturnmid = int((inicio + fin)/2)mergesort_2(array, inicio, mid)mergesort_2(array, mid+1, fin)merge_temp(array, inicio, mid+1, fin)def merge_temp(array, init1, init2, end2):global num_compare, num_copymemo_temp = 10temp = list(range(memo_temp))end1 = init2-1i = 0while init1 <= end1 and init2 <= end2:num_compare += 1num_copy += 1if array < array:temp = arrayinit2 += 1else:temp = arrayinit1 += 1i += 1if i >= memo_temp:merge_insert(array, temp, i, init1, end1, init2, end2)init1 = init1 + (init2 - 1 - end1)end1 = init2 - 1i = 0merge_insert(array, temp, i, init1, end1, init2, end2)def merge_insert(array, temp, leng, init1, end1, init2, end2):global num_compare, num_copyinit_copy = init1 + (init2-end1-1) - lengj = init2-1while end1 >= init1:num_copy += 1array = arrayj -= 1end1 -= 1init1 = init_copy + lengj = 0while init_copy < init1:num_copy += 1array = tempinit_copy += 1j += 1def quicksort(array):global num_compare, num_copyquicksort_2(array, 0, len(array)-1)return num_compare, num_copydef quicksort_2(array, min_pos, max_pos):global num_compare, num_copyif min_pos >= max_pos:returnimin_pos = min_posimax_pos = max_posmid = array[int((min_pos + max_pos)/2)]while imin_pos <= imax_pos:while array < mid:num_compare += 1imin_pos += 1while array > mid:imax_pos -= 1num_compare += 1num_compare += 3if imin_pos == imax_pos:imin_pos += 1imax_pos -= 1breakif imin_pos < imax_pos:num_copy +=3temp = arrayarray = arrayarray = tempimin_pos += 1imax_pos -= 1if imax_pos - min_pos < max_pos - imin_pos:quicksort_2(array, min_pos, imax_pos)quicksort_2(array, imin_pos, max_pos)else:quicksort_2(array, imin_pos, max_pos)quicksort_2(array, min_pos, imax_pos)# Run programif __name__ == "__main__":main()And this is the report (in csv) with my computer:Code:Algorithm,Array size,Comparisons,Units,Copies,Units,Execution timeBubble Sort ,10,0.4400,N*N,0.5700,N*N,0.0000Direct Insertion,10,0.2700,N*N,0.3600,N*N,0.0000Binary Insertion,10,0.2200,N*N,0.3700,N*N,0.0000Direct Selection,10,0.4500,N*N,0.2700,N*N,0.0000ShellSort ,10,1.3029,N*Ln(N),2.3018,N*Ln(N),0.0000HeapSort ,10,1.6069,N*Ln(N),3.0835,N*Ln(N),0.0000QuickSort ,10,2.6926,N*Ln(N),1.1726,N*Ln(N),0.0000MergeSort ,10,1.1726,N*Ln(N),2.0846,N*Ln(N),0.0000Bubble Sort ,100,0.4905,N*N,0.6393,N*N,0.0000Direct Insertion,100,0.2228,N*N,0.2327,N*N,0.0000Binary Insertion,100,0.0528,N*N,0.2329,N*N,0.0000Direct Selection,100,0.4950,N*N,0.0297,N*N,0.0000ShellSort ,100,2.0564,N*Ln(N),3.2225,N*Ln(N),0.0000HeapSort ,100,2.2583,N*Ln(N),2.3430,N*Ln(N),0.0000QuickSort ,100,2.3018,N*Ln(N),0.9316,N*Ln(N),0.0000MergeSort ,100,1.2269,N*Ln(N),3.1139,N*Ln(N),0.0000Bubble Sort ,1000,0.4993,N*N,0.7307,N*N,0.1003Direct Insertion,1000,0.2446,N*N,0.2456,N*N,0.0529Binary Insertion,1000,0.0086,N*N,0.2456,N*N,0.0625Direct Selection,1000,0.4995,N*N,0.0030,N*N,0.0845ShellSort ,1000,3.4492,N*Ln(N),4.6781,N*Ln(N),0.0219HeapSort ,1000,2.4396,N*Ln(N),2.0350,N*Ln(N),0.0157QuickSort ,1000,2.3769,N*Ln(N),0.9715,N*Ln(N),0.0000MergeSort ,1000,1.2628,N*Ln(N),9.3996,N*Ln(N),0.0000Bubble Sort ,10000,0.4998,N*N,0.7534,N*N,10.6998Direct Insertion,10000,0.2512,N*N,0.2513,N*N,6.6190Binary Insertion,10000,0.0012,N*N,0.2513,N*N,3.4726Direct Selection,10000,0.5000,N*N,0.0003,N*N,6.1176ShellSort ,10000,6.6957,N*Ln(N),8.0182,N*Ln(N),0.1693HeapSort ,10000,2.5553,N*Ln(N),1.8904,N*Ln(N),0.0469QuickSort ,10000,2.3768,N*Ln(N),1.0155,N*Ln(N),0.0313MergeSort ,10000,1.3280,N*Ln(N),56.7526,N*Ln(N),0.7800ShellSort ,100000,15.2216,N*Ln(N),16.5545,N*Ln(N),4.6824HeapSort ,100000,2.6231,N*Ln(N),1.8023,N*Ln(N),0.6550QuickSort ,100000,2.3659,N*Ln(N),1.0095,N*Ln(N),0.3543MergeSort ,100000,1.3615,N*Ln(N),437.2988,N*Ln(N),72.9004ShellSort ,1000000,36.4804,N*Ln(N),37.8177,N*Ln(N),143.0511HeapSort ,1000000,2.6633,N*Ln(N),1.7407,N*Ln(N),8.9103QuickSort ,1000000,2.3073,N*Ln(N),1.0095,N*Ln(N),4.2588Edit:In the results, Units are given in N*N or N*log(N) where N is the number of array elements (array size).For example if the comparisons are 0.456 N*N for an array of 100 elements, it means that there have been 4560 comparisons in total.The calculation is done by dividing 4560 by 100*100.

author: Picuino
author_rank: Super Contributor
timestamp: July 23, 2022, 05:47:28 pm
content: I'm going to add this 'new' algoritm:https://www.eevblog.com/forum/programming/interesting-new-sort-algorithm/msg4314406/#msg4314406Code: (Python)"""Comparison between sorting algorithmsCopyright (c) 2022 PicuinoPermission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in allcopies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THESOFTWARE."""import copyimport mathimport randomimport timenum_compare = 0num_copy = 0def main():algorithms = [{"name":"Bubble Sort", "function":bubble_sort},{"name":"Direct Selection", "function":direct_selection},{"name":"Direct Insertion", "function":direct_insertion},{"name":"Binary Insertion", "function":binary_insertion},{"name":"New sort", "function":new_sort},]algorithms_not_used = [{"name":"ShellSort", "function":shellsort},{"name":"MergeSort", "function":mergesort},{"name":"HeapSort", "function":heapsort},{"name":"QuickSort", "function":quicksort},]# Initialize report filereport_head = "Algorithm,Array size,Comparisons,Units,Copies,Units,Execution time"with open("Report.csv", "wt") as report_file:report_file.write(report_head + '\n')print(report_head)# Sort arrays of different sizesarray_sizes = [10, 100, 1000, 10000, 100000, 1000000]for array_size in array_sizes:array = generate_random_array(array_size)for algorithm in algorithms:if array_size > 10000 and algorithm["function"] in (bubble_sort, direct_insertion, binary_insertion, direct_selection, new_sort):continuereport = sort(algorithm, array)print(report)report_file.write(report + '\n')def sort(algorithm, array):global num_compare, num_copyarray_copy = copy.copy(array)num_compare = num_copy = 0run_time = time.time()algorithm["function"](array_copy)run_time = time.time() - run_timeif is_sorted(array_copy):report = generate_report(algorithm, len(array), num_compare, num_copy, run_time)else:report = "Array not sorted."return reportdef generate_random_array(array_size):array = []for i in range(array_size):array.append(random.getrandbits(32))return arraydef is_sorted(array):for i in range(1, len(array)):if array[i-1] > array:return Falsereturn Truedef generate_report(algorithm, array_size, num_compare, num_copy, run_time):report = []report.append("%-16s" % algorithm["name"])report.append("%d" % array_size)# Number of comparisonsif algorithm['function'] in (shellsort, heapsort, quicksort, mergesort):report.append("%1.4f,N*Ln(N)" % (num_compare/(array_size * math.log(array_size))))else:report.append("%1.4f,N*N" % (num_compare/float(array_size * array_size)))# Number of copiesif algorithm['function'] in (shellsort, heapsort, quicksort, mergesort):report.append("%1.4f,N*Ln(N)" % (num_copy/(array_size * math.log(array_size))))else:report.append("%1.4f,N*N" % (num_copy/float(array_size * array_size)))# Execution timereport.append("%1.4f" % run_time)return ','.join(report)def bubble_sort(array):global num_compare, num_copyfor i in range(len(array), 1, -1):moves = 0for j in range(1, i):num_compare += 1if array[j - 1] > array:num_copy += 3temp = arrayarray = array[j - 1]array[j -1] = tempmoves = 1if moves == 0:breakdef binary_insertion(array):global num_compare, num_copyfor pos in range(1, len(array)):num_copy += 1temp = arrayinf = 0sup = poswhile inf < sup:med = int((inf + sup) / 2)num_compare += 1if temp > array:inf = med + 1else:sup = medwhile pos > inf:num_copy += 1array = array[pos - 1]pos -= 1num_copy += 1array = tempreturn num_compare, num_copydef direct_selection(array):global num_compare, num_copyt_inf = 0t_sup = len(array) - 1while t_inf < t_sup:p_min = t_infj = t_inf + 1while j <= t_sup:num_compare += 1if array < array:p_min = jj += 1num_copy += 3temp = arrayarray = arrayarray = tempt_inf += 1def direct_insertion(array):global num_compare, num_copyi = 1while i < len(array):num_copy += 1temp = arrayj = iwhile j >= 1:num_compare += 1num_copy += 1if array[j - 1] > temp:array = array[j - 1]j -= 1else:breakarray = tempi += 1def new_sort(array):global num_compare, num_copyfor i in range(len(array)):for j in range(len(array)):num_compare += 1if array < array:num_copy += 3temp = arrayarray = arrayarray = tempdef shellsort(array):global num_compare, num_copyi = len(array)step = 1while i >= 4:i //= 2step *= 2while step >= 1:i = stepwhile i < len(array):num_copy += 1temp = arrayj = iwhile j >= step:num_compare += 1num_copy += 1if array[j-step] > temp:array = array[j-step]j -= stepelse:breakarray = tempi += 1step //= 2def heapsort(array):global num_compare, num_copy# Make heap structurepointer = int((len(array) - 1) / 2)while pointer >= 0:heapsort_screen(array, pointer, len(array) - 1)pointer -= 1# Sort arraypointer = len(array) - 1while pointer > 0:num_copy += 3temp = arrayarray = arrayarray = temppointer -= 1heapsort_screen(array, 0, pointer)def heapsort_screen(array, array_min, array_max):global num_compare, num_copydown = array_min * 2 + 1if (down > array_max):returnnum_copy += 1temp = arraywhile down <= array_max:if down < array_max:num_compare += 1if array[down + 1] > array:down += 1num_compare += 1if temp > array:breaknum_copy += 1array = arrayarray_min = downdown = down * 2 + 1num_copy += 1array = tempdef mergesort(array):mergesort_2(array, 0, len(array)-1)def mergesort_2(array, inicio, fin):global num_compare, num_copyif fin <= inicio+1:num_compare += 1if array<array:num_copy += 3temp = arrayarray = arrayarray = tempreturnmid = int((inicio + fin)/2)mergesort_2(array, inicio, mid)mergesort_2(array, mid+1, fin)merge_temp(array, inicio, mid+1, fin)def merge_temp(array, init1, init2, end2):global num_compare, num_copymemo_temp = 10temp = list(range(memo_temp))end1 = init2-1i = 0while init1 <= end1 and init2 <= end2:num_compare += 1num_copy += 1if array < array:temp = arrayinit2 += 1else:temp = arrayinit1 += 1i += 1if i >= memo_temp:merge_insert(array, temp, i, init1, end1, init2, end2)init1 = init1 + (init2 - 1 - end1)end1 = init2 - 1i = 0merge_insert(array, temp, i, init1, end1, init2, end2)def merge_insert(array, temp, leng, init1, end1, init2, end2):global num_compare, num_copyinit_copy = init1 + (init2-end1-1) - lengj = init2-1while end1 >= init1:num_copy += 1array = arrayj -= 1end1 -= 1init1 = init_copy + lengj = 0while init_copy < init1:num_copy += 1array = tempinit_copy += 1j += 1def quicksort(array):global num_compare, num_copyquicksort_2(array, 0, len(array)-1)return num_compare, num_copydef quicksort_2(array, min_pos, max_pos):global num_compare, num_copyif min_pos >= max_pos:returnimin_pos = min_posimax_pos = max_posmid = array[int((min_pos + max_pos)/2)]while imin_pos <= imax_pos:while array < mid:num_compare += 1imin_pos += 1while array > mid:imax_pos -= 1num_compare += 1num_compare += 3if imin_pos == imax_pos:imin_pos += 1imax_pos -= 1breakif imin_pos < imax_pos:num_copy +=3temp = arrayarray = arrayarray = tempimin_pos += 1imax_pos -= 1if imax_pos - min_pos < max_pos - imin_pos:quicksort_2(array, min_pos, imax_pos)quicksort_2(array, imin_pos, max_pos)else:quicksort_2(array, imin_pos, max_pos)quicksort_2(array, min_pos, imax_pos)# Run programif __name__ == "__main__":main()Results:Code:Bubble Sort ,10,0.4400,N*N,0.8400,N*N,0.0000Direct Selection,10,0.4500,N*N,0.2700,N*N,0.0000Direct Insertion,10,0.3500,N*N,0.4400,N*N,0.0000Binary Insertion,10,0.2300,N*N,0.4600,N*N,0.0000New sort ,10,1.0000,N*N,0.9000,N*N,0.0000Bubble Sort ,100,0.4947,N*N,0.7074,N*N,0.0000Direct Selection,100,0.4950,N*N,0.0297,N*N,0.0000Direct Insertion,100,0.2453,N*N,0.2552,N*N,0.0000Binary Insertion,100,0.0533,N*N,0.2556,N*N,0.0000New sort ,100,1.0000,N*N,0.7080,N*N,0.0000Bubble Sort ,1000,0.4989,N*N,0.7663,N*N,0.1003Direct Selection,1000,0.4995,N*N,0.0030,N*N,0.0534Direct Insertion,1000,0.2564,N*N,0.2574,N*N,0.0625Binary Insertion,1000,0.0086,N*N,0.2574,N*N,0.0690New sort ,1000,1.0000,N*N,0.7602,N*N,0.1537Bubble Sort ,10000,0.4998,N*N,0.7441,N*N,11.3787Direct Selection,10000,0.5000,N*N,0.0003,N*N,6.5603Direct Insertion,10000,0.2481,N*N,0.2482,N*N,7.2902Binary Insertion,10000,0.0012,N*N,0.2482,N*N,3.6161New sort ,10000,1.0000,N*N,0.7073,N*N,13.3711Edit: Error corrected in new_sort()

author: Picuino
author_rank: Super Contributor
timestamp: July 23, 2022, 06:39:44 pm
content: This 'new sort' algorithm is worst than bubble sort and not more 'intuitive'

author: Picuino
author_rank: Super Contributor
timestamp: July 23, 2022, 06:41:07 pm
content: Can somebody help me improve the merge algorithm?It seems to run slower than it should.

author: SparkyFX
author_rank: Frequent Contributor
timestamp: July 23, 2022, 07:03:22 pm
content: Quote from: Picuino on July 23, 2022, 05:36:33 pmSorting has always been a very sophisticated problem.Interpreted languages might heavily optimize what you are trying to achieve there (or the opposite), as they might not be optimizing for sort speed but for memory utilization or something else.Have you considered comparing it to pythons built in sort function?

author: Picuino
author_rank: Super Contributor
timestamp: July 23, 2022, 07:29:07 pm
content: I do not intend to make practical sorting algorithms. I would have to do that in C by sorting, for example, strings.The sort method built in Python is written in C and optimized, it cannot be compared to the others.As a curiosity, Python uses the TimSort algorithm which is a mix derived from merge sort and insertion sort.https://en.wikipedia.org/wiki/TimsortWhat I intend with this program are two things:1 - Show how the different algorithms are programmed.2 - Compare with each other the different algorithms with the number of comparisons, the number of data movements and the relative execution time of each of them.

author: Picuino
author_rank: Super Contributor
timestamp: July 23, 2022, 07:57:22 pm
content: Program updated with the TimSort algorithm. Lists are used in this implementation. This needs to be changed so that TimSort can work with an array in place.Code:"""Comparison between sorting algorithmsCopyright (c) 2022 PicuinoPermission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in allcopies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THESOFTWARE."""import copyimport mathimport randomimport timenum_compare = 0num_copy = 0def main():algorithms = [{"name":"Bubble Sort", "function":bubble_sort},{"name":"Direct Selection", "function":direct_selection},{"name":"Direct Insertion", "function":direct_insertion},{"name":"Binary Insertion", "function":binary_insertion},{"name":"ShellSort", "function":shellsort},{"name":"MergeSort", "function":mergesort},{"name":"TimSort", "function":timsort},{"name":"HeapSort", "function":heapsort},{"name":"QuickSort", "function":quicksort},]# Initialize report filereport_head = "Algorithm,Array size,Comparisons,Units,Copies,Units,Execution time"with open("Report.csv", "wt") as report_file:report_file.write(report_head + '\n')print(report_head)# Sort arrays of different sizesarray_sizes = [10, 100, 1000, 10000, 100000, 1000000]fast_algorithms = (timsort, heapsort, quicksort)for array_size in array_sizes:array = generate_random_array(array_size)for algorithm in algorithms:if array_size > 10000 and not algorithm["function"] in fast_algorithms:continuereport = sort(algorithm, array)print(report)report_file.write(report + '\n')def sort(algorithm, array):global num_compare, num_copyarray_copy = copy.copy(array)num_compare = num_copy = 0run_time = time.time()algorithm["function"](array_copy)run_time = time.time() - run_timeif is_sorted(array_copy):report = generate_report(algorithm, len(array), num_compare, num_copy, run_time)else:report = "Array not sorted."return reportdef generate_random_array(array_size):array = []for i in range(array_size):array.append(random.getrandbits(32))return arraydef is_sorted(array):for i in range(1, len(array)):if array[i-1] > array:return Falsereturn Truedef generate_report(algorithm, array_size, num_compare, num_copy, run_time):report = []report.append("%-16s" % algorithm["name"])report.append("%d" % array_size)# Number of comparisonsif algorithm['function'] in (shellsort, heapsort, quicksort, timsort, mergesort):report.append("%1.4f,N*Ln(N)" % (num_compare/(array_size * math.log(array_size))))else:report.append("%1.4f,N*N" % (num_compare/float(array_size * array_size)))# Number of copiesif algorithm['function'] in (shellsort, heapsort, quicksort, timsort, mergesort):report.append("%1.4f,N*Ln(N)" % (num_copy/(array_size * math.log(array_size))))else:report.append("%1.4f,N*N" % (num_copy/float(array_size * array_size)))# Execution timereport.append("%1.4f" % run_time)return ','.join(report)def bubble_sort(array):global num_compare, num_copyfor i in range(len(array), 1, -1):moves = 0for j in range(1, i):num_compare += 1if array[j - 1] > array:num_copy += 3temp = arrayarray = array[j - 1]array[j -1] = tempmoves = 1if moves == 0:breakdef binary_insertion(array):global num_compare, num_copyfor pos in range(1, len(array)):num_copy += 1temp = arrayinf = 0sup = poswhile inf < sup:med = int((inf + sup) / 2)num_compare += 1if temp > array:inf = med + 1else:sup = medwhile pos > inf:num_copy += 1array = array[pos - 1]pos -= 1num_copy += 1array = tempdef direct_selection(array):global num_compare, num_copyt_inf = 0t_sup = len(array) - 1while t_inf < t_sup:p_min = t_infj = t_inf + 1while j <= t_sup:num_compare += 1if array < array:p_min = jj += 1num_copy += 3temp = arrayarray = arrayarray = tempt_inf += 1def direct_insertion(array):global num_compare, num_copyi = 1while i < len(array):num_copy += 1temp = arrayj = iwhile j >= 1:num_compare += 1num_copy += 1if array[j - 1] > temp:array = array[j - 1]j -= 1else:breakarray = tempi += 1def shellsort(array):global num_compare, num_copyi = len(array)step = 1while i >= 4:i //= 2step *= 2while step >= 1:i = stepwhile i < len(array):num_copy += 1temp = arrayj = iwhile j >= step:num_compare += 1num_copy += 1if array[j-step] > temp:array = array[j-step]j -= stepelse:breakarray = tempi += 1step //= 2def mergesort(array):mergesort_2(array, 0, len(array)-1)def mergesort_2(array, inicio, fin):global num_compare, num_copyif fin <= inicio+1:num_compare += 1if array<array:num_copy += 3temp = arrayarray = arrayarray = tempreturnmid = int((inicio + fin)/2)mergesort_2(array, inicio, mid)mergesort_2(array, mid+1, fin)merge_temp(array, inicio, mid+1, fin)def merge_temp(array, init1, init2, end2):global num_compare, num_copymemo_temp = 10temp = list(range(memo_temp))end1 = init2-1i = 0while init1 <= end1 and init2 <= end2:num_compare += 1num_copy += 1if array < array:temp = arrayinit2 += 1else:temp = arrayinit1 += 1i += 1if i >= memo_temp:merge_insert(array, temp, i, init1, end1, init2, end2)init1 = init1 + (init2 - 1 - end1)end1 = init2 - 1i = 0merge_insert(array, temp, i, init1, end1, init2, end2)def merge_insert(array, temp, leng, init1, end1, init2, end2):global num_compare, num_copyinit_copy = init1 + (init2-end1-1) - lengj = init2-1while end1 >= init1:num_copy += 1array = arrayj -= 1end1 -= 1init1 = init_copy + lengj = 0while init_copy < init1:num_copy += 1array = tempinit_copy += 1j += 1def heapsort(array):global num_compare, num_copy# Make heap structurepointer = int((len(array) - 1) / 2)while pointer >= 0:heapsort_screen(array, pointer, len(array) - 1)pointer -= 1# Sort arraypointer = len(array) - 1while pointer > 0:num_copy += 3temp = arrayarray = arrayarray = temppointer -= 1heapsort_screen(array, 0, pointer)def heapsort_screen(array, array_min, array_max):global num_compare, num_copydown = array_min * 2 + 1if (down > array_max):returnnum_copy += 1temp = arraywhile down <= array_max:if down < array_max:num_compare += 1if array[down + 1] > array:down += 1num_compare += 1if temp > array:breaknum_copy += 1array = arrayarray_min = downdown = down * 2 + 1num_copy += 1array = tempdef timsort(array):n = len(array)minrun = timsort_find_minrun(n)for start in range(0, n, minrun):end = min(start + minrun - 1, n - 1)timsort_insertion(array, start, end)size = minrunwhile size < n:for left in range(0, n, 2 * size):mid = min(n - 1, left + size - 1)right = min((left + 2 * size - 1), (n - 1))timsort_merge(array, left, mid, right)size = 2 * sizedef timsort_find_minrun(n):TIMSORT_MINIMUM = 32r = 0while n >= TIMSORT_MINIMUM:r |= n & 1n >>= 1return n + rdef timsort_insertion(array, left, right):global num_compare, num_copyfor i in range(left+1, right+1):num_copy += 1element = arrayj = i - 1num_compare += 1while element < array and j >= left :num_copy += 1array[j+1] = arrayj -= 1num_compare += 1num_copy += 1array[j+1] = elementreturn arraydef timsort_merge(array, l, m, r):global num_compare, num_copyarray_length1 = m - l + 1array_length2 = r - mleft = []right = []for i in range(0, array_length1):num_copy += 1left.append(array[l + i])for i in range(0, array_length2):num_copy += 1right.append(array[m + 1 + i])i=0j=0k=lwhile j < array_length2 and i < array_length1:num_compare += 1if left <= right:num_copy += 1array = lefti += 1else:num_copy += 1array = rightj += 1k += 1while i < array_length1:num_copy += 1array = leftk += 1i += 1while j < array_length2:num_copy += 1array = rightk += 1j += 1def quicksort(array):global num_compare, num_copyquicksort_2(array, 0, len(array)-1)def quicksort_2(array, min_pos, max_pos):global num_compare, num_copyif min_pos >= max_pos:returnimin_pos = min_posimax_pos = max_posmid = array[int((min_pos + max_pos)/2)]while imin_pos <= imax_pos:while array < mid:num_compare += 1imin_pos += 1while array > mid:imax_pos -= 1num_compare += 1num_compare += 3if imin_pos == imax_pos:imin_pos += 1imax_pos -= 1breakif imin_pos < imax_pos:num_copy +=3temp = arrayarray = arrayarray = tempimin_pos += 1imax_pos -= 1if imax_pos - min_pos < max_pos - imin_pos:quicksort_2(array, min_pos, imax_pos)quicksort_2(array, imin_pos, max_pos)else:quicksort_2(array, imin_pos, max_pos)quicksort_2(array, min_pos, imax_pos)# Run programif __name__ == "__main__":main()Results:Code:Algorithm,Array size,Comparisons,Units,Copies,Units,Execution timeBubble Sort ,10,0.4400,N*N,0.8100,N*N,0.0000Direct Selection,10,0.4500,N*N,0.2700,N*N,0.0000Direct Insertion,10,0.3600,N*N,0.4500,N*N,0.0000Binary Insertion,10,0.2300,N*N,0.4500,N*N,0.0000ShellSort ,10,1.3463,N*Ln(N),2.3452,N*Ln(N),0.0000MergeSort ,10,1.1292,N*Ln(N),1.9978,N*Ln(N),0.0000TimSort ,10,1.5635,N*Ln(N),1.9543,N*Ln(N),0.0000HeapSort ,10,1.6503,N*Ln(N),3.0835,N*Ln(N),0.0000QuickSort ,10,2.3018,N*Ln(N),0.9120,N*Ln(N),0.0000Bubble Sort ,100,0.4947,N*N,0.8259,N*N,0.0000Direct Selection,100,0.4950,N*N,0.0297,N*N,0.0156Direct Insertion,100,0.2849,N*N,0.2948,N*N,0.0000Binary Insertion,100,0.0533,N*N,0.2951,N*N,0.0000ShellSort ,100,2.2909,N*Ln(N),3.4570,N*Ln(N),0.0000MergeSort ,100,1.2551,N*Ln(N),3.3658,N*Ln(N),0.0000TimSort ,100,1.9587,N*Ln(N),2.6123,N*Ln(N),0.0000HeapSort ,100,2.2301,N*Ln(N),2.3083,N*Ln(N),0.0000QuickSort ,100,2.1954,N*Ln(N),1.0228,N*Ln(N),0.0000Bubble Sort ,1000,0.4994,N*N,0.7659,N*N,0.1380Direct Selection,1000,0.4995,N*N,0.0030,N*N,0.0781Direct Insertion,1000,0.2563,N*N,0.2573,N*N,0.0690Binary Insertion,1000,0.0086,N*N,0.2573,N*N,0.0312ShellSort ,1000,3.4677,N*Ln(N),4.6966,N*Ln(N),0.0157MergeSort ,1000,1.2632,N*Ln(N),9.5585,N*Ln(N),0.0000TimSort ,1000,1.9841,N*Ln(N),2.8565,N*Ln(N),0.0000HeapSort ,1000,2.4354,N*Ln(N),2.0328,N*Ln(N),0.0000QuickSort ,1000,2.3320,N*Ln(N),1.0145,N*Ln(N),0.0156Bubble Sort ,10000,0.4999,N*N,0.7448,N*N,11.0654Direct Selection,10000,0.5000,N*N,0.0003,N*N,6.4206Direct Insertion,10000,0.2484,N*N,0.2485,N*N,6.8213Binary Insertion,10000,0.0012,N*N,0.2485,N*N,3.7271ShellSort ,10000,7.4491,N*Ln(N),8.7716,N*Ln(N),0.2006MergeSort ,10000,1.3276,N*Ln(N),56.4443,N*Ln(N),0.8181TimSort ,10000,1.5810,N*Ln(N),2.6737,N*Ln(N),0.0467HeapSort ,10000,2.5559,N*Ln(N),1.8915,N*Ln(N),0.0535QuickSort ,10000,2.2253,N*Ln(N),1.0183,N*Ln(N),0.0156TimSort ,100000,1.6376,N*Ln(N),2.7715,N*Ln(N),0.7021HeapSort ,100000,2.6224,N*Ln(N),1.8021,N*Ln(N),0.7022QuickSort ,100000,2.3369,N*Ln(N),1.0141,N*Ln(N),0.3701TimSort ,1000000,1.6947,N*Ln(N),2.8551,N*Ln(N),9.6082HeapSort ,1000000,2.6631,N*Ln(N),1.7406,N*Ln(N),9.9156QuickSort ,1000000,2.2399,N*Ln(N),1.0164,N*Ln(N),4.4138

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 23, 2022, 08:08:27 pm
content: I'm not a fan of Python (as you probably already figured) and not aware in details about how it performs using varying data structures, but at first sight, I would say that the merge_insert() function is probably a bottleneck here.

author: Mechatrommer
author_rank: Super Contributor
timestamp: July 23, 2022, 08:29:17 pm
content: can you translate and add this (originally VB) into your setup? change data type if necessary. its a variant of shell sort, verify it separately first as it can be unstable on some array indexing type. i suggest to test on random (unsorted), some/half part already sorted and nearly sorted data... to simulate near all real life situations. ymmv. (ps: i want to see how it fair up with python's timsort)Code:Public Sub GB_ShellSort(A() As Integer)Dim temp As IntegerDim increm As LongDim numOfEntries As LongDim i As LongDim j As LongnumOfEntries = UBound(A) + 1 '(base 0 array)increm = numOfEntries * (5 / 11)Do Until increm < 1For i = increm To numOfEntries - 1 '(base 0 array)temp = A(i)For j = i - increm To 0 Step -incremIf temp >= A(j) Then Exit ForA(j + increm) = A(j)Next jA(j + increm) = tempNext iincrem = increm * (5 / 11)LoopEnd Sub

author: Picuino
author_rank: Super Contributor
timestamp: July 23, 2022, 10:29:34 pm
content: This algorithm is exactly to my algorithm sellsort with one change:the factor (5/11) in my case is (1 / 2)this ratio (5/11) does not work for some reason on some array sizes.Comparing both:Code:Algorithm,Array size,Randomness,Comparisons,Units,Copies,Units,Execution timeShellSort , 100, 1.0, 1.9826, N*ln(N), 3.1921, N*ln(N), 0.0000ShellSort 2 , 100, 1.0, 1.6395, N*ln(N), 2.6883, N*ln(N), 0.0000ShellSort , 100, 0.2, 1.5461, N*ln(N), 2.6622, N*ln(N), 0.0000ShellSort 2 , 100, 0.2, 1.1965, N*ln(N), 2.1237, N*ln(N), 0.0000ShellSort , 1000, 1.0, 2.2608, N*ln(N), 3.4893, N*ln(N), 0.0000ShellSort 2 , 1000, 1.0, 1.8845, N*ln(N), 2.9947, N*ln(N), 0.0157ShellSort , 1000, 0.2, 1.9155, N*ln(N), 3.0896, N*ln(N), 0.0000ShellSort 2 , 1000, 0.2, 1.6555, N*ln(N), 2.7094, N*ln(N), 0.0000ShellSort , 10000, 1.0, 2.8872, N*ln(N), 4.2443, N*ln(N), 0.0781ShellSort 2 , 10000, 1.0, 2.1232, N*ln(N), 3.2822, N*ln(N), 0.0623ShellSort , 10000, 0.2, 2.4435, N*ln(N), 3.7594, N*ln(N), 0.1381ShellSort 2 , 10000, 0.2, 1.9361, N*ln(N), 3.0524, N*ln(N), 0.0625ShellSort , 100000, 1.0, 3.7974, N*ln(N), 5.1441, N*ln(N), 1.3666ShellSort 2 , 100000, 1.0, 2.2413, N*ln(N), 3.4288, N*ln(N), 0.8182ShellSort , 100000, 0.2, 3.3230, N*ln(N), 4.6364, N*ln(N), 1.2349ShellSort 2 , 100000, 0.2, 2.1061, N*ln(N), 3.2598, N*ln(N), 0.7868ShellSort , 1000000, 1.0, 4.8703, N*ln(N), 6.2096, N*ln(N), 21.1200ShellSort 2 , Array not sorted.ShellSort , 1000000, 0.2, 4.0135, N*ln(N), 5.3252, N*ln(N), 20.1193ShellSort 2 , Array not sorted.Translated algorithm:Code:def shellsort_2(array):global num_compare, num_copyarray_size = len(array)increment = array_size * 5 // 11while increment >= 1:i = incrementwhile i < array_size:num_copy += 1temp = arrayj = iwhile j >= increment:num_compare += 1if array[j - increment] > temp:num_copy += 1array = array[j - increment]j -= incrementelse:breaknum_copy += 1array = tempi += 1increment = increment * 5 // 11Your algorithm works correctly if I change the ratio back to 1/2

author: Mechatrommer
author_rank: Super Contributor
timestamp: July 23, 2022, 10:39:45 pm
content: Quote from: Picuino on July 23, 2022, 10:29:34 pmyes for ratio 1/2 is standard shellsort, but the 5/11 i derived from value 2.2 (gonnet baeza) as described inhttps://en.wikipedia.org/wiki/Shellsortmaybe you can tweak the ratio to get correct rounding off error. i can see some improvement compared to classic shellsort when both can sort correctly.

author: Picuino
author_rank: Super Contributor
timestamp: July 23, 2022, 10:45:04 pm
content: I have added a parameter (randomness) of variable randomness for the arrays used, so that the algorithms can be tested with arrays with different sorting/randomness level.Program:Code:"""Comparison between sorting algorithmsCopyright (c) 2022 PicuinoPermission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in allcopies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THESOFTWARE."""import copyimport mathimport randomimport timenum_compare = 0num_copy = 0def main():algorithms = [{ "name":"Bubble Sort","function":bubble_sort,"units": "N*N","maxsize": 10000,},{ "name":"Direct Selection","function":direct_selection,"units": "N*N","maxsize": 10000,},{ "name":"Direct Insertion","function":direct_insertion,"units": "N*N","maxsize": 10000,},{ "name":"Binary Insertion","function":binary_insertion,"units": "N*N","maxsize": 10000,},{ "name":"MergeSort","function":mergesort,"units": "N*ln(N)","maxsize": 100000,},{ "name":"ShellSort","function":shellsort,"units": "N*ln(N)","maxsize": 100000,},{ "name":"TimSort","function":timsort,"units": "N*ln(N)","maxsize": 1000000,},{ "name":"HeapSort","function":heapsort,"units": "N*ln(N)","maxsize": 1000000,},{ "name":"QuickSort","function":quicksort,"units": "N*ln(N)","maxsize": 1000000,},]algorithms_not_used = []# Initialize report filereport_head = "Algorithm,Array size,Randomness,Comparisons,Units,Copies,Units,Execution time"with open("Report.csv", "wt") as report_file:report_file.write(report_head + '\n')print(report_head)# Sort arrays of different sizes and randomnessarray_types = [( 100, 1), ( 100, 0.1),( 1000, 1), ( 1000, 0.1),( 10000, 1), ( 10000, 0.1),( 100000, 1), ( 100000, 0.1),(1000000, 1), (1000000, 0.1),]for array_type in array_types:array = generate_random_array(*array_type)for algorithm in algorithms:if array_type > algorithm['maxsize']:continuereport = sort(algorithm, array, array_type)print(report)report_file.write(report + '\n')def sort(algorithm, array, array_type):global num_compare, num_copyarray_copy = copy.copy(array)num_compare = num_copy = 0run_time = time.time()algorithm["function"](array_copy)run_time = time.time() - run_timeif is_sorted(array_copy):report = generate_report(algorithm, array_type, num_compare, num_copy, run_time)else:report = "%-16s, Array not sorted." % algorithm["name"]return reportdef generate_random_array(array_size, randomness):array = []for i in range(array_size):array.append(random.getrandbits(32))if randomness >= 1:return arrayarray.sort()if randomness <= 0:return arrayfor i in range(int(array_size * randomness * 0.5)):a = random.randint(0, array_size - 1)b = random.randint(0, array_size - 1)array, array = array, arrayreturn arraydef is_sorted(array):for i in range(1, len(array)):if array[i-1] > array:return Falsereturn Truedef generate_report(algorithm, array_type, num_compare, num_copy, run_time):report = []array_size, randomness = array_type, array_type# Algorithm namereport.append("%-16s" % algorithm["name"])# Array size and randomnessreport.append("%8d, %1.1f" % array_type)# Number of comparisonsif algorithm['units'] == "N*ln(N)":report.append("%8.4f, N*ln(N)" % (num_compare/(array_size * math.log(array_size))))else:report.append("%8.4f, N*N " % (num_compare/float(array_size * array_size)))# Number of copiesif algorithm['units'] == "N*ln(N)":report.append("%8.4f, N*ln(N)" % (num_copy/(array_size * math.log(array_size))))else:report.append("%8.4f, N*N " % (num_copy/float(array_size * array_size)))# Execution timereport.append("%8.4f" % run_time)return ', '.join(report)def bubble_sort(array):global num_compare, num_copyfor i in range(len(array), 1, -1):moves = 0for j in range(1, i):num_compare += 1if array[j - 1] > array:num_copy += 3temp = arrayarray = array[j - 1]array[j -1] = tempmoves = 1if moves == 0:breakdef binary_insertion(array):global num_compare, num_copyfor pos in range(1, len(array)):num_copy += 1temp = arrayinf = 0sup = poswhile inf < sup:med = int((inf + sup) / 2)num_compare += 1if temp > array:inf = med + 1else:sup = medwhile pos > inf:num_copy += 1array = array[pos - 1]pos -= 1num_copy += 1array = tempdef direct_selection(array):global num_compare, num_copyt_inf = 0t_sup = len(array) - 1while t_inf < t_sup:p_min = t_infj = t_inf + 1while j <= t_sup:num_compare += 1if array < array:p_min = jj += 1num_copy += 3temp = arrayarray = arrayarray = tempt_inf += 1def direct_insertion(array):global num_compare, num_copyi = 1while i < len(array):num_copy += 1temp = arrayj = iwhile j >= 1:num_compare += 1num_copy += 1if array[j - 1] > temp:array = array[j - 1]j -= 1else:breakarray = tempi += 1def shellsort(array):global num_compare, num_copyarray_size = len(array)step = array_size // 2while step >= 1:i = stepwhile i < len(array):num_copy += 1temp = arrayj = iwhile j >= step:num_compare += 1if array[j-step] > temp:num_copy += 1array = array[j-step]j -= stepelse:breaknum_copy += 1array = tempi += 1step //= 2def mergesort(array):mergesort_2(array, 0, len(array)-1)def mergesort_2(array, inicio, fin):global num_compare, num_copyif fin <= inicio+1:num_compare += 1if array<array:num_copy += 3temp = arrayarray = arrayarray = tempreturnmid = int((inicio + fin)/2)mergesort_2(array, inicio, mid)mergesort_2(array, mid+1, fin)merge_temp(array, inicio, mid+1, fin)def merge_temp(array, init1, init2, end2):global num_compare, num_copymemo_temp = 10temp = list(range(memo_temp))end1 = init2-1i = 0while init1 <= end1 and init2 <= end2:num_compare += 1num_copy += 1if array < array:temp = arrayinit2 += 1else:temp = arrayinit1 += 1i += 1if i >= memo_temp:merge_insert(array, temp, i, init1, end1, init2, end2)init1 = init1 + (init2 - 1 - end1)end1 = init2 - 1i = 0merge_insert(array, temp, i, init1, end1, init2, end2)def merge_insert(array, temp, leng, init1, end1, init2, end2):global num_compare, num_copyinit_copy = init1 + (init2-end1-1) - lengj = init2-1while end1 >= init1:num_copy += 1array = arrayj -= 1end1 -= 1init1 = init_copy + lengj = 0while init_copy < init1:num_copy += 1array = tempinit_copy += 1j += 1def heapsort(array):global num_compare, num_copy# Make heap structurepointer = int((len(array) - 1) / 2)while pointer >= 0:heapsort_screen(array, pointer, len(array) - 1)pointer -= 1# Sort arraypointer = len(array) - 1while pointer > 0:num_copy += 3temp = arrayarray = arrayarray = temppointer -= 1heapsort_screen(array, 0, pointer)def heapsort_screen(array, array_min, array_max):global num_compare, num_copydown = array_min * 2 + 1if (down > array_max):returnnum_copy += 1temp = arraywhile down <= array_max:if down < array_max:num_compare += 1if array[down + 1] > array:down += 1num_compare += 1if temp > array:breaknum_copy += 1array = arrayarray_min = downdown = down * 2 + 1num_copy += 1array = tempdef timsort(array):n = len(array)minrun = timsort_find_minrun(n)for start in range(0, n, minrun):end = min(start + minrun - 1, n - 1)timsort_insertion(array, start, end)size = minrunwhile size < n:for left in range(0, n, 2 * size):mid = min(n - 1, left + size - 1)right = min((left + 2 * size - 1), (n - 1))timsort_merge(array, left, mid, right)size = 2 * sizedef timsort_find_minrun(n):TIMSORT_MINIMUM = 32r = 0while n >= TIMSORT_MINIMUM:r |= n & 1n >>= 1return n + rdef timsort_insertion(array, left, right):global num_compare, num_copyfor i in range(left+1, right+1):num_copy += 1element = arrayj = i - 1num_compare += 1while element < array and j >= left :num_copy += 1array[j+1] = arrayj -= 1num_compare += 1num_copy += 1array[j+1] = elementreturn arraydef timsort_merge(array, l, m, r):global num_compare, num_copyarray_length1 = m - l + 1array_length2 = r - mleft = []right = []for i in range(0, array_length1):num_copy += 1left.append(array[l + i])for i in range(0, array_length2):num_copy += 1right.append(array[m + 1 + i])i=0j=0k=lwhile j < array_length2 and i < array_length1:num_compare += 1if left <= right:num_copy += 1array = lefti += 1else:num_copy += 1array = rightj += 1k += 1while i < array_length1:num_copy += 1array = leftk += 1i += 1while j < array_length2:num_copy += 1array = rightk += 1j += 1def quicksort(array):global num_compare, num_copyquicksort_2(array, 0, len(array)-1)def quicksort_2(array, min_pos, max_pos):global num_compare, num_copyif min_pos >= max_pos:returnimin_pos = min_posimax_pos = max_posmid = array[int((min_pos + max_pos)/2)]while imin_pos <= imax_pos:while array < mid:num_compare += 1imin_pos += 1while array > mid:imax_pos -= 1num_compare += 1num_compare += 3if imin_pos == imax_pos:imin_pos += 1imax_pos -= 1breakif imin_pos < imax_pos:num_copy +=3temp = arrayarray = arrayarray = tempimin_pos += 1imax_pos -= 1if imax_pos - min_pos < max_pos - imin_pos:quicksort_2(array, min_pos, imax_pos)quicksort_2(array, imin_pos, max_pos)else:quicksort_2(array, imin_pos, max_pos)quicksort_2(array, min_pos, imax_pos)# Run programif __name__ == "__main__":main()Results:Code:Algorithm,Array size,Randomness,Comparisons,Units,Copies,Units,Execution timeBubble Sort , 100, 1.0, 0.4935, N*N , 0.8349, N*N , 0.0000Direct Selection, 100, 1.0, 0.4950, N*N , 0.0297, N*N , 0.0000Direct Insertion, 100, 1.0, 0.2880, N*N , 0.2979, N*N , 0.0000Binary Insertion, 100, 1.0, 0.0532, N*N , 0.2981, N*N , 0.0000MergeSort , 100, 1.0, 1.2529, N*ln(N), 3.3397, N*ln(N), 0.0000ShellSort , 100, 1.0, 1.8696, N*ln(N), 3.1117, N*ln(N), 0.0000TimSort , 100, 1.0, 2.0933, N*ln(N), 2.7491, N*ln(N), 0.0000HeapSort , 100, 1.0, 2.2171, N*ln(N), 2.3213, N*ln(N), 0.0000QuickSort , 100, 1.0, 2.3039, N*ln(N), 0.9967, N*ln(N), 0.0000Bubble Sort , 100, 0.1, 0.4422, N*N , 0.0558, N*N , 0.0000Direct Selection, 100, 0.1, 0.4950, N*N , 0.0297, N*N , 0.0000Direct Insertion, 100, 0.1, 0.0285, N*N , 0.0384, N*N , 0.0000Binary Insertion, 100, 0.1, 0.0514, N*N , 0.0384, N*N , 0.0000MergeSort , 100, 0.1, 1.0293, N*ln(N), 2.1671, N*ln(N), 0.0000ShellSort , 100, 0.1, 1.4071, N*ln(N), 2.5059, N*ln(N), 0.0000TimSort , 100, 0.1, 0.6818, N*ln(N), 1.3811, N*ln(N), 0.0000HeapSort , 100, 0.1, 2.3452, N*ln(N), 2.4538, N*ln(N), 0.0000QuickSort , 100, 0.1, 1.4614, N*ln(N), 0.0261, N*ln(N), 0.0000Bubble Sort , 1000, 1.0, 0.4990, N*N , 0.7374, N*N , 0.1003Direct Selection, 1000, 1.0, 0.4995, N*N , 0.0030, N*N , 0.0532Direct Insertion, 1000, 1.0, 0.2468, N*N , 0.2478, N*N , 0.0625Binary Insertion, 1000, 1.0, 0.0086, N*N , 0.2478, N*N , 0.0468MergeSort , 1000, 1.0, 1.2652, N*ln(N), 9.4297, N*ln(N), 0.0222ShellSort , 1000, 1.0, 2.2320, N*ln(N), 3.4645, N*ln(N), 0.0000TimSort , 1000, 1.0, 1.9630, N*ln(N), 2.8368, N*ln(N), 0.0156HeapSort , 1000, 1.0, 2.4373, N*ln(N), 2.0380, N*ln(N), 0.0000QuickSort , 1000, 1.0, 2.3049, N*ln(N), 1.0102, N*ln(N), 0.0000Bubble Sort , 1000, 0.1, 0.4927, N*N , 0.0909, N*N , 0.0691Direct Selection, 1000, 0.1, 0.4995, N*N , 0.0030, N*N , 0.0690Direct Insertion, 1000, 0.1, 0.0313, N*N , 0.0323, N*N , 0.0000Binary Insertion, 1000, 0.1, 0.0085, N*N , 0.0323, N*N , 0.0065MergeSort , 1000, 0.1, 1.0881, N*ln(N), 5.8510, N*ln(N), 0.0000ShellSort , 1000, 0.1, 1.8065, N*ln(N), 2.9764, N*ln(N), 0.0000TimSort , 1000, 0.1, 1.0241, N*ln(N), 1.9425, N*ln(N), 0.0000HeapSort , 1000, 0.1, 2.5312, N*ln(N), 2.1214, N*ln(N), 0.0000QuickSort , 1000, 0.1, 1.4520, N*ln(N), 0.0634, N*ln(N), 0.0000Bubble Sort , 10000, 1.0, 0.4999, N*N , 0.7520, N*N , 10.6330Direct Selection, 10000, 1.0, 0.5000, N*N , 0.0003, N*N , 6.2194Direct Insertion, 10000, 1.0, 0.2508, N*N , 0.2509, N*N , 6.7740Binary Insertion, 10000, 1.0, 0.0012, N*N , 0.2509, N*N , 3.5269MergeSort , 10000, 1.0, 1.3278, N*ln(N), 56.7051, N*ln(N), 0.7867ShellSort , 10000, 1.0, 2.8618, N*ln(N), 4.2204, N*ln(N), 0.0938TimSort , 10000, 1.0, 1.5854, N*ln(N), 2.6782, N*ln(N), 0.0469HeapSort , 10000, 1.0, 2.5569, N*ln(N), 1.8920, N*ln(N), 0.0535QuickSort , 10000, 1.0, 2.4283, N*ln(N), 1.0001, N*ln(N), 0.0220Bubble Sort , 10000, 0.1, 0.4977, N*N , 0.0883, N*N , 6.3979Direct Selection, 10000, 0.1, 0.5000, N*N , 0.0003, N*N , 6.1972Direct Insertion, 10000, 0.1, 0.0295, N*N , 0.0296, N*N , 0.8181Binary Insertion, 10000, 0.1, 0.0012, N*N , 0.0296, N*N , 0.4389MergeSort , 10000, 0.1, 1.2287, N*ln(N), 32.4017, N*ln(N), 0.4701ShellSort , 10000, 0.1, 2.2982, N*ln(N), 3.6079, N*ln(N), 0.0688TimSort , 10000, 0.1, 1.1231, N*ln(N), 2.2584, N*ln(N), 0.0467HeapSort , 10000, 0.1, 2.6448, N*ln(N), 1.9635, N*ln(N), 0.0469QuickSort , 10000, 0.1, 1.4713, N*ln(N), 0.0759, N*ln(N), 0.0311MergeSort , 100000, 1.0, 1.3615, N*ln(N), 436.6518, N*ln(N), 75.9208ShellSort , 100000, 1.0, 3.7946, N*ln(N), 5.1413, N*ln(N), 1.3263TimSort , 100000, 1.0, 1.6377, N*ln(N), 2.7716, N*ln(N), 0.6866HeapSort , 100000, 1.0, 2.6228, N*ln(N), 1.8023, N*ln(N), 0.7023QuickSort , 100000, 1.0, 2.2740, N*ln(N), 1.0101, N*ln(N), 0.3321MergeSort , 100000, 0.1, 1.2854, N*ln(N), 245.8826, N*ln(N), 45.8585ShellSort , 100000, 0.1, 2.8985, N*ln(N), 4.2070, N*ln(N), 1.0720TimSort , 100000, 0.1, 1.1866, N*ln(N), 2.3467, N*ln(N), 0.6020HeapSort , 100000, 0.1, 2.6961, N*ln(N), 1.8612, N*ln(N), 0.7178QuickSort , 100000, 0.1, 1.4983, N*ln(N), 0.0805, N*ln(N), 0.2319TimSort , 1000000, 1.0, 1.6938, N*ln(N), 2.8542, N*ln(N), 9.4139HeapSort , 1000000, 1.0, 2.6632, N*ln(N), 1.7407, N*ln(N), 9.2069QuickSort , 1000000, 1.0, 2.3135, N*ln(N), 1.0077, N*ln(N), 4.5677TimSort , 1000000, 0.1, 1.2283, N*ln(N), 2.4098, N*ln(N), 9.0971HeapSort , 1000000, 0.1, 2.7237, N*ln(N), 1.7892, N*ln(N), 8.5798QuickSort , 1000000, 0.1, 1.5192, N*ln(N), 0.0844, N*ln(N), 3.1254

author: Picuino
author_rank: Super Contributor
timestamp: July 23, 2022, 10:48:13 pm
content: Quote from: Mechatrommer on July 23, 2022, 10:39:45 pmYes, there is a improvement in shellsort 2 in the number of comparisons, number of copies and execution time. But i don't know how to eliminate the error.Code:Algorithm,Array size,Randomness,Comparisons,Units,Copies,Units,Execution timeShellSort , 100, 1.0, 1.9826, N*ln(N), 3.1921, N*ln(N), 0.0000ShellSort 2 , 100, 1.0, 1.6395, N*ln(N), 2.6883, N*ln(N), 0.0000ShellSort , 100, 0.2, 1.5461, N*ln(N), 2.6622, N*ln(N), 0.0000ShellSort 2 , 100, 0.2, 1.1965, N*ln(N), 2.1237, N*ln(N), 0.0000ShellSort , 1000, 1.0, 2.2608, N*ln(N), 3.4893, N*ln(N), 0.0000ShellSort 2 , 1000, 1.0, 1.8845, N*ln(N), 2.9947, N*ln(N), 0.0157ShellSort , 1000, 0.2, 1.9155, N*ln(N), 3.0896, N*ln(N), 0.0000ShellSort 2 , 1000, 0.2, 1.6555, N*ln(N), 2.7094, N*ln(N), 0.0000ShellSort , 10000, 1.0, 2.8872, N*ln(N), 4.2443, N*ln(N), 0.0781ShellSort 2 , 10000, 1.0, 2.1232, N*ln(N), 3.2822, N*ln(N), 0.0623ShellSort , 10000, 0.2, 2.4435, N*ln(N), 3.7594, N*ln(N), 0.1381ShellSort 2 , 10000, 0.2, 1.9361, N*ln(N), 3.0524, N*ln(N), 0.0625ShellSort , 100000, 1.0, 3.7974, N*ln(N), 5.1441, N*ln(N), 1.3666ShellSort 2 , 100000, 1.0, 2.2413, N*ln(N), 3.4288, N*ln(N), 0.8182ShellSort , 100000, 0.2, 3.3230, N*ln(N), 4.6364, N*ln(N), 1.2349ShellSort 2 , 100000, 0.2, 2.1061, N*ln(N), 3.2598, N*ln(N), 0.7868ShellSort , 1000000, 1.0, 4.8703, N*ln(N), 6.2096, N*ln(N), 21.1200ShellSort 2 , Array not sorted.ShellSort , 1000000, 0.2, 4.0135, N*ln(N), 5.3252, N*ln(N), 20.1193ShellSort 2 , Array not sorted.

author: Mechatrommer
author_rank: Super Contributor
timestamp: July 23, 2022, 11:29:41 pm
content: maybe you can change from increment = array_size * 5 // 11 to increment = array_size * (5 // 11) or increment = (array_size * 5) // 11... tokuda's ratio is (4 / 9) could be even worseymmv. (ps: or just maybe there is a flaw in the implementation of the "gap" in original code) or maybe from the website (attached) isCode:increment = (array_size * 5 - 1) // 11...increment = ((increment * 5) // 11) - 1

author: brucehoult
author_rank: Super Contributor
timestamp: July 24, 2022, 01:22:38 am
content: Quote from: Picuino on July 23, 2022, 06:39:44 pmIt's not all that much worse. Always twice as many comparisons, true, but fewer swaps.The number of swaps is intriguingly close to sqrt(0.5) aka sqrt(2)/2.

author: brucehoult
author_rank: Super Contributor
timestamp: July 24, 2022, 03:20:42 am
content: I reckon if Tim is allowed his own algorithm then so am I.Code:{ "name":"BruceSort","function":brucesort,"units": "N*ln(N)","maxsize": 1000000,},:::def brucesort(array):global num_compare, num_copyif len(array) > 8: brucesort_2(array, 0, len(array)-1)direct_insertion(array)def brucesort_2(array, min_pos, max_pos):global num_compare, num_copya, b, c = array, array[int((min_pos + max_pos)/2)], arrayif (b<a) != (b<c):pivot = belif (a<b) != (a<c):pivot = aelse:pivot = ci, j = min_pos, max_poswhile True:orig_i, orig_j = i, jwhile pivot > array: i += 1while pivot < array: j -= 1num_compare += (i-orig_i) + (orig_j-j) + 2if i >= j: breaknum_copy += 3array, array = array, arrayi, j = i+1, j-1if i == j: i, j = i+1, j-1if j - min_pos > 8:brucesort_2(array, min_pos, j)if max_pos - i > 8:brucesort_2(array, i, max_pos)ResultsOn M1 Mac:Code:QuickSort , 1000000, 1.0, 2.3490, N*ln(N), 1.0075, N*ln(N), 4.1489BruceSort , 1000000, 1.0, 1.6734, N*ln(N), 1.1433, N*ln(N), 3.3282QuickSort , 1000000, 0.1, 1.4773, N*ln(N), 0.0848, N*ln(N), 2.9112BruceSort , 1000000, 0.1, 1.3723, N*ln(N), 0.2303, N*ln(N), 2.0927On ThreadRipper 2990wx:Code:QuickSort , 1000000, 1.0, 2.3291, N*ln(N), 1.0047, N*ln(N), 4.4930BruceSort , 1000000, 1.0, 1.7684, N*ln(N), 1.1295, N*ln(N), 3.6325QuickSort , 1000000, 0.1, 1.4799, N*ln(N), 0.0845, N*ln(N), 2.9236BruceSort , 1000000, 0.1, 1.3792, N*ln(N), 0.2300, N*ln(N), 1.9506

author: Picuino
author_rank: Super Contributor
timestamp: July 24, 2022, 08:52:38 am
content: Quote from: Mechatrommer on July 23, 2022, 11:29:41 pmFinally!! this is what works:increment = int(increment * (5/11))With better results than:increment = int(increment * (1/2))

author: Picuino
author_rank: Super Contributor
timestamp: July 24, 2022, 08:59:11 am
content: Quote from: brucehoult on July 24, 2022, 03:20:42 amVery impressive!! Better than QuickSort!!It appears to be an enhancement to QuickSort.

author: Picuino
author_rank: Super Contributor
timestamp: July 24, 2022, 09:01:31 am
content: Quote from: Picuino on July 24, 2022, 08:52:38 amOnly for 100 000 arrays. In 1000 000 arrays the algorithm fails again.

author: brucehoult
author_rank: Super Contributor
timestamp: July 24, 2022, 09:56:35 am
content: Quote from: Picuino on July 24, 2022, 08:59:11 amYesss. Improve quicksort by doing a slow insertion sort after it!

author: mariush
author_rank: Super Contributor
timestamp: July 24, 2022, 10:19:38 am
content: You should check outfluxsort (stable adaptive branchless , hybrid mergesort/quicksort) :https://github.com/scandum/fluxsortquadsort (stable bottom-up adaptive branchless merge sort - name comes from sorting 4 variables at once) :https://github.com/scandum/quadsortcrumsort (UNstable adaptive hybrid mergesort/quicksort, claims better than fluxsort at 1M+ records) :https://github.com/scandum/crumsortMay want to look into sorting using SIMD / AVX and other tricksex. quicksort using AVX :https://github.com/WojciechMula/simd-sortalso see the PDF referenced in the link above.

author: westfw
author_rank: Super Contributor
timestamp: July 27, 2022, 09:51:37 pm
content: QuoteWhy are so many of the tests showing 0.0 execution time?

author: mariush
author_rank: Super Contributor
timestamp: July 27, 2022, 10:25:23 pm
content: it says size=10 so i assume 10 values can be sorted in nanoseconds on 4+ ghz processors.

author: brucehoult
author_rank: Super Contributor
timestamp: July 27, 2022, 10:26:51 pm
content: Quote from: westfw on July 27, 2022, 09:51:37 pmBecause sorting 10 items takes less than 0.00005 seconds even with the worst algorithm, even written in Python?

author: westfw
author_rank: Super Contributor
timestamp: July 28, 2022, 02:59:33 am
content: Duh! I entirely missed that there were examples that varied the number of items!

author: Mechatrommer
author_rank: Super Contributor
timestamp: July 28, 2022, 06:19:47 am
content: For small set of numbers to sort, pc will happily sort with the the new but worst algorithm you put in at 0s.. real life is millions or billions of unsorted numbers. Thats why we came up with some hacks or tricks to deal with since even the best sort will take a while.. such as precomputation and save it somewhere for later use. when inserting value to already sorted values, it only take O(log(n)) instead of dreadful O(n.log (n) ).it looks cute, but not when we are talking billions of numbers.

author: mariush
author_rank: Super Contributor
timestamp: July 28, 2022, 07:46:12 am
content: It's worth pointing out one more thing ... how much extra memory each algorithm uses.I could very easily "sort" 1m numbers by making multiple double linked lists (ex element.previous - element.value - element.next ) and basically inserting each value as I loop through the million entries into one such list or by other tricks that use a lot of memory.For example, let's say the sort key is a 32 bit number ... I could have as many 256 element "buckets" as needed, by using the top 24 bits of the sort key as an id for the bucket. In each bucket then, you can have up to keys and the positions in the array where these keys show upWhen you're done parsing the whole set of numbers, you can just sort the buckets by their id and merge everything in one output array.

author: Mechatrommer
author_rank: Super Contributor
timestamp: July 28, 2022, 08:24:47 am
content: If you have 2-16GB ram at disposal, you can sort almost any 4bytes length integer with O (n) speed. but thats not the popular way..