Common sorting algorithms implemented in Python

Keywords: Python shell

Although there is a sort() function in python that can easily sort lists and tuples in one sentence, in order to better understand the algorithm and data structure, Hanzhou has implemented six commonly used sorting algorithms in Python. The first three algorithms have time complexity of O(n^2) and the last three have time complexity of O (logn). If there are any shortcomings, please correct them.

1. Insert sort

The basic operation of insertion sorting is to insert a data into the ordered data,
Then a new ordered data is obtained, which can be used to sort a small amount of data;
First, take the first one as the ordered one, then insert it into the front and sort it every time

def insert_sort(list):
    for i in range(len(list)):#Traverse the list one by one and insert the ith element
        for j in range(i):#Treat the first i-1 element as an ordered list, and insert the i-th
            if list[i] < list[j]:#Compare the elements to be sorted with the ordered list in turn. If the larger one is found, insert
                list.insert(j, list.pop(i))#Pop up this element from the original list and insert it into the new location of the original list
                break#If there is no insertion at the end of the loop, the element position is appropriate
    return list

2. Bubble sorting

It repeatedly visited the sequence to be sorted,
Compare two elements at a time and swap them if they are out of order.
The work of the interview series is repeated until there is no need to exchange,
That is to say, the sequence has been sorted.
The name of this algorithm comes from the fact that the smaller the element, the more slowly it will "float" to the top of the sequence through exchange.

def bubble_sort(list):
    for i in range(len(list)):#All elements need to be bubbled, record the number of bubbling times, and take a picture of each element
        for j in range(len(list)-i-1):#Bubble unsorted elements
            if list[j]>list[j+1]:#If the element is larger
                list[j],list[j+1]=list[j+1],list[j]#Swap positions, put them in the back
    return list

3. Select Sorting

First, find the smallest (large) element in the unsorted sequence and store it at the beginning of the sorted sequence,
Then, continue to look for the smallest (largest) element from the remaining unsorted elements,
It is then placed at the end of the sorted sequence.
And so on until all elements are sorted.

def selection_sort(list):
	finish=[]#Ordered list
    while list:#When the list is not empty
        k=0#Record the position of the minimum value for each cycle
        for i in range(1,len(list)):#Find the minimum value in the existing unordered list
            if list[k]>list[i]:
                k=i#Update minimum position
        finish.append(list.pop(k))#Pop up the minimum value and add it to the sequence table
    return finish

4. Hill sorting

Hill sorting is to group records by a certain increment of subscript, and use direct insertion sorting algorithm to sort each group;
As the increment decreases, each group contains more and more keywords,
When the increment is reduced to 1, the whole file is just divided into a group, and the algorithm is terminated
(when understanding the following code snippet, it is recommended to substitute the code from i=0 for drawing comprehension)

def shell_sort(list):
	gap=len(list)#Initial increment length, set as table length
    while gap>1:#Exit sorting when increment is 1
        gap//=2#Halve increments
        for i in range(gap,len(list)):#Insert and sort each group. The original array is divided into gap groups with gap elements at the beginning
            for j in range(i%gap,i,gap):#Sort the first i elements in each group. The interval of data in each group is incremental gap
                if list[j]>list[i]:#If the size order is not correct, exchange, and ensure that list[i] is the largest element in each group
    return list

5. Merge and sort

Merge sorting is a typical application of Divide and Conquer.
The ordered subsequences are combined to get the completely ordered sequences;
That is to say, first make each subsequence orderly, and then make subsequence segments orderly.
If two ordered tables are combined into one ordered table, it is called two-way merge.

def merge_sort(list):
	if len(list)<2: return list#Return a single element to the merge list
    left=list[0:mid]#Left list
    right=list[mid:]#Right list
    return merge(merge_sort(left),merge_sort(right))
    #After dividing the left and right lists, the merged sequential tables will be returned to the previous level for merging

def merge(left,right):
    //Merge sort merge two sequential tables into one list
    :param left: Sequence table on the left
    :param right: Sequence table on the right
    :return: Combined ordered list
    finish=[]#Combined ordered list
    while left or right:#When at least one of two sequential tables is not empty
        if left and right:#When both sequential tables are not empty
            if left[0]<right[0]:#The left list element is smaller
            else:#Right list elements are small or equal
        elif left and not right:#Right list space
            finish +=left
        elif not left and right:#Left column surface empty
            finish +=right
    return finish#Return the merged list

6. Quick sorting

In essence, fast sorting is also the application of divide and conquer,
Select a reference value, and put the larger one in the array on the right,
Smaller than the reference value is placed on the left side of the list,
Then recursively use the above steps to the left and right of this list to get an ordered list.

(1) Method 1: digging and filling

This method is equivalent to the idea of using pointer, which is tedious, but the space complexity is low

def quick_sort(list):
	return qsort(list, 0, len(list) - 1)
    #List to be sorted, starting position and ending position

def qsort(list, start, end):
    if start < end:
        left = start
        right = end
        key = list[start]#First take out a reference value
        return list#Prove to have reached the minimum, just return to the list
    while left < right:#If the left and right end elements do not meet, it proves that a round of sorting is not over
        while left < right and list[right] >= key:#Compare with the reference value from the tail first
            right -= 1#Move the right pointer to the left
        if left < right:
            # The reason for breaking the while loop is that list [right] < = key
            #To avoid destroying the outer while loop in the previous loop, add this if
            list[left] = list[right]
            #Give the right value to the left, and the left initial value has been paid to the key as the reference value. Do not worry about data loss
            left += 1#Left lateral shift
        while left < right and list[left] < key:#Compare from head to reference
            left += 1#Left lateral shift
        if left < right:
            # To avoid destroying the outer while loop in the previous loop, add this if
            # Explain that the reason for breaking the while loop is list [left] > = key
            list[right] = list[left]#Left value to right pointer
            right -= 1#Shift right value left
    list[left] = key  # At this time, left=right, fill the pit with key
    qsort(list, start, left - 1)#Use recursion for left and right lists
    qsort(list, left + 1, end)
    return list

(2) Method 2

This method has a small amount of code, is easy to understand, and is very Python, but has a high space complexity

def quickSort1(list):
	    if len(list)<2:
        return list
    left=[];right=[]#Left and right empty array
    key=list.pop()#Reference value
    //I thought about writing key=list[0], but the program crashed. After thinking about it, I found that,
    //If you choose not to pop up the first element, the following code will always put it at the beginning,
    //Then the subsequent recursion will not get the answer
    for i in list:#Loop this list to group
        if i>key:#Greater than base, added to right array
        else:#Otherwise add to left array
    #Call left and right arrays recursively, and finally merge them to return
    return quickSort1(left)+[key]+quickSort1(right)

100000 data sorting time test:

1. Sorting test function

def testnum(n,sort):
    //Test sorting algorithm time
    :param sort: Sorting algorithm
    :param n:Sort array length
    :return: Sorting time
    nums = list(range(n))#Generate number list
    random.shuffle(nums)#There will be sequence table disorder
    start=time.time()#Starting time
    end=time.time()#Sort end time
    return (end-start)#Return algorithm sort time

2. Test the main function

def main():
    n=20000#Length of sequence to be sorted
    print("Insertion sort%s Time spent on data:%s s" %(n,testnum(n,insert_sort)))
    print("Bubble sort%s Time spent on data:%s s" % (n, testnum(n, bubble_sort)))
    print("Selection sort%s Time spent on data:%s s" % (n, testnum(n, selection_sort)))
    print("Shell Sort%s Time spent on data:%s s" % (n, testnum(n, shell_sort)))
    print("Merge sort%s Time spent on data:%s s" % (n, testnum(n, merge_sort)))
    print("Method 1 quick sorting%s Time spent on data:%s s" % (n, testnum(n, quick_sort)))
    print("Method 2 quick sorting%s Time spent on data:%s s" % (n, testnum(n, quickSort1)))

The results are as follows:

Due to different machines, the results may be different

Reprint please indicate the source!

Published 3 original articles, won praise 1, visited 30
Private letter follow

Posted by chamal on Sun, 01 Mar 2020 02:39:42 -0800