Python Classic Sorting Algorithm

Posted by goodluck4287 on Sat, 28 Dec 2019 11:49:40 +0100

https://www.cnblogs.com/onepixel/p/7674659.html This article is nice

https://www.bilibili.com/video/av685670?from=search&seid=1637373535603658338 This motion picture is excellent

https://www.icourse163.org/course/ZJU-93001 MOOC Zhejiang Big Data Structure Chen Yue and He Qin-ming


Bubble sort, select sort, insert sort are the three slowest and most classic sort algorithms

Quick sorting is generally believed to be the fastest known sorting for large random number columns

bubble sort

The simplest sorting algorithm is also the least efficient because it must swap before the final location is known, wasting many "swap operations"

If the list is sorted, it is best if no swap is needed during traversal, and if sorted, it can be terminated earlier. Bubbles under this modification are often referred to as short bubble sorting


Time Complexity: Average O(n^2), Worst O(n^2), Best O(n)

Spatial Complexity: O(1)

Stable

#Test input array
alist = [27, 33, 28, 4, 2, 26, 13, 35, 8, 14]

#Bubble sort
for i in range(len(alist)-1):
    for j in range(len(alist)-1-i):
        if alist[j] > alist[j+1]:
            alist[j],alist[j+1] = alist[j+1],alist[j]
        
#Sort results output
print('sorted:',alist)

Select Sort selection sort

Selective sorting improves bubble sorting by only exchanging once per iteration of the list


Time Complexity: Average O(n^2), Worst O(n^2), Best O(n^2)

Spatial Complexity: O(1)

Instable

#Test input array
alist = [27, 33, 28, 4, 2, 26, 13, 35, 8, 14]

#Select Sort
for i in range(len(alist)-1):
    least = i
    for j in range(i+1,len(alist)):
        if alist[j] < alist[least]:
            least = j
    if least != i:
        alist[least],alist[i] = alist[i],alist[least]

#Sort results output
print('sorted:',alist)

Insert sort insertion sort

It always maintains a sorted sublist at the lower position of the list, then "inserts" each new item back to the previous sublist, making the sorted sublist a larger item


Time Complexity: Average O(n^2), Worst O(n^2), Best O(n)

Spatial Complexity: O(1)

Stable

#Test input array
alist = [27, 33, 28, 4, 2, 26, 13, 35, 8, 14]

#Insert Sort
for i in range(1,len(alist)):
    j = i;
    while j>0 and alist[j-1]>alist[j]:
        alist[j-1],alist[j] = alist[j],alist[j-1]
        j -= 1
        
#Sort results output
print('sorted:',alist)

Hill sort shell

It was invented by Shell in 1959. The first breakthrough in O(n^2) sorting is an improvement on simple insert sorting. Unlike insert sorting, it gives priority to elements that are farther apart, also known as "descending incremental sorting"

It is an improvement on the following two features of insert sorting: efficient operation on data that is almost sorted to achieve the efficiency of linear sorting; generally inefficient because insert sorting can only move data one bit at a time

Hill sorting improves the performance of insert sorting by dividing all elements of the comparison into zones.This allows an element to make a big step forward toward its final position at once

Gap concept, gap decreases, the last step is to insert sort, but it's almost in order now

gap is the Hill sorting core

The well-known gap set Marcin Ciura's gap sequence, gap s = [701, 301, 132, 57, 23, 10, 4, 1], but the following example uses a sequence whose array length is continuously divided by 2 as a gap s


Time Complexity: Average O(n(logn)^2), Worst O(n^2), Best O(n)

Spatial Complexity: O(1)

Instable

#Test input array
alist = [27, 33, 28, 4, 2, 26, 13, 35, 8, 14]

#Shell Sort
gap = len(alist)//2
while gap>0:
    #Sort each gap by insertion
    for i in range(gap,len(alist)):
        j = i
        while j>=gap and alist[j-gap]>alist[j]:
            alist[j-gap],alist[j] = alist[j],alist[j-gap]
            j -= gap           
    gap = gap//2

#Sort results output
print('sorted:',alist)

merge sort

The divide-and-conquer strategy to improve performance is a typical application of divide-and-conquer

Merge Sort is a recursive algorithm that constantly splits lists into half

Two-way merge and multiple merge

The disadvantage is that the merge process requires additional storage space


Time Complexity: Average O(nlogn), Worst O(nlogn), Best O(nlogn)

Spatial Complexity: O(n)

Stable

#Test input array
alist = [27, 33, 28, 4, 2, 26, 13, 35, 8, 14]

#Merge Sort
def merge_sort(ilist):   
    def merge(left, right):
        result = []
        while left and right:
            result.append((left if left[0] <= right[0] else right).pop(0))
        return result + left + right
    
    if len(ilist) <= 1:
        return ilist
    mid = len(ilist) // 2
    return merge(merge_sort(ilist[:mid]), merge_sort(ilist[mid:]))

#Sort results output
print('sorted:',merge_sort(alist))

quick sort

Same as merge sort, divide and conquer without extra storage

Is an improvement on bubble sorting

Usually significantly faster than other algorithms because its internal loops can be efficiently accomplished on most architectures

Simple versions are just as bad as merge sort and require extra storage, but you can change to in-place without extra space


Time Complexity: Average O(nlogn), Worst O(n^2), Best O(nlogn)

Spatial Complexity: O(nlogn)

Instable

#Test input array
alist = [27, 33, 28, 4, 2, 26, 13, 35, 8, 14]

#Quick Sort
def quick_sort(ilist): 
    length = len(ilist)
    if length <= 1:
        return ilist
    else:
        # Use the last element as the first pivot
        pivot = ilist.pop()
        # Put elements greater than pivot in greater list
        # Put elements lesser than pivot in lesser list
        greater, lesser = [], []
        for element in ilist:
            if element > pivot:
                greater.append(element)
            else:
                lesser.append(element)
        return quick_sort(lesser) + [pivot] + quick_sort(greater)

#Sort results output
print('sorted:',quick_sort(alist))

heap sort

Is an improvement on selection ordering

The algorithm designed with heap data structure approximates a complete binary tree

A heap usually solves a large root heap or a small root heap through a one-dimensional array


Time Complexity: Average O(nlogn), Worst O(nlogn), Best O(nlogn)

Spatial Complexity: O(1)

Instable

#Test input array
alist = [27, 33, 28, 4, 2, 26, 13, 35, 8, 14]

#Heap Sorting
def heapify(unsorted, index, heap_size):
    largest = index
    left_index = 2 * index + 1
    right_index = 2 * index + 2
    if left_index < heap_size and unsorted[left_index] > unsorted[largest]:
        largest = left_index

    if right_index < heap_size and unsorted[right_index] > unsorted[largest]:
        largest = right_index

    if largest != index:
        unsorted[largest], unsorted[index] = unsorted[index], unsorted[largest]
        heapify(unsorted, largest, heap_size)
        
def heap_sort(unsorted):
    n = len(unsorted)
    for i in range(n // 2 - 1, -1, -1):
        heapify(unsorted, i, n)
    for i in range(n - 1, 0, -1):
        unsorted[0], unsorted[i] = unsorted[i], unsorted[0]
        heapify(unsorted, 0, i)
    return unsorted

#Sort results output
print('sorted:',heap_sort(alist))

Topics: Python shell Big Data