Classical sorting algorithms - with python code

Reference links:

https://www.cnblogs.com/fivestudy/p/10212306.html

https://blog.csdn.net/qq_43549984/article/details/89426394#Bubble_Sort_21

1. What sort algorithm?

Sorting algorithm is one of the algorithm, "Data Structures and Algorithms" in the most basic.

Sorting algorithm can be divided into internal sorting and external sorting .

  • Internal sorting sorts the data records in memory.
  • External sorting because a great sort of data, one can not accommodate all sort of record, in the sorting process requires access to external memory.

Common internal sorting algorithms : bubble, insert, merge, select, fast row, Hill, heap sort, radix sort and so on.

Sorting algorithm complexity

Algorithm algorithm Time Complexity Time Complexity Space Complexity Space complexity
Best Average Worst Worst stability
QuickSort fast row O(n log(n)) O(n log(n)) O (n ^ 2) O(n log(n)) Unstable
MergeSort merge O(n log(n)) O(n log(n)) O(n log(n)) O (n) stable
BubbleSort bubbling O (n) O (n ^ 2) O (n ^ 2) O (1) stable
InsertionSort insert O (n) O (n ^ 2) O (n ^ 2) O (1) stable
SelectionSort selection O (n ^ 2) O (n ^ 2) O (n ^ 2) O (1) Unstable

2. Time complexity

Order of the square O (n ^ 2) insert select bubble
Linearity of the order O(n log(n)) Fast row Merger Heapsort
Linear Order O (n) Radix Sort Bucket sort Sort box

3. Stability

stable bubble insert Merger Cardinal number
Unstable select Fast row Hill Heapsort

4. The bubble sort

Bubble Sort sorting algorithm is a simple, it repeatedly through the list, comparing the two neighboring elements, if the wrong order, the switching thereof. The algorithm is a relatively sort, it is a small or large elements "bubble" to the top of the list are named. Although the algorithm is very simple, but for most problems, it is too slow.

4.1 parsing algorithm steps

  • Compare adjacent elements. If the first is greater than the second, the two of them exchanged.
  • Do the same work for each pair of adjacent elements, from the beginning of the first pair to the end of the last pair. Once this is done, the last element is the biggest number.
  • Repeat these steps for all the elements, in addition to already sorted.
  • Continued to repeat the above steps for each time fewer and fewer elements, a pair of numbers until there is no need to compare.

4.2 graphic

bubble
bubble

4.3 Code

"""
def bubble_sort(alist):
    # 方式1
    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]
    return alist
"""

def bubble_sort(alist):
    # 方式2
    for i in range(len(alist)-1):
        flag = True
        for j in range(len(alist)-1-i):
            if alist[j] > alist[j + 1]:
                alist[j], alist[j + 1] = alist[j + 1], alist[j]
                flag = False
        if flag is True:
            break
    return alist


def test_bubble_sort():
    import random
    alist = list(range(10))
    random.shuffle(alist)
    result = bubble_sort(alist)
    print(result)

test_bubble_sort()

4.4 parsed

First, the way 1

  1. n-1 cycles of
  2. In each round the loop, regardless of whether the size of the adjacent elements have been ordered. It will be the size comparison.
  3. Recursively determining continuously, after n-1 wheel query to obtain a final result.

Second, the way 2

  1. n-1 Query wheel
  2. Each round query, before elements to determine the size of the adjacent stand flag: refers to the need to replace the default. After each loop is entered if the condition adjacent the front element is greater than the back, so they exchange data, and change the flag is false, until the end of the current round of circulation.
  3. Next cycle begins, initialization flag, when the current round of circulation if all adjacent elements meet the order (ascending or descending), will round out of circulation.
  4. When (when ascending or descending) initial default parameters, the n-th wheel through the outer loop, the inner loop is executed only break1 times, then out of the loop, the optimal time complexity it is O (n) . The worst case, the inner loop is executed n times also requires, worst case time complexity is O (n ^ 2) .

5. Selection Sort

Selection Sort sorting algorithm is a comparison in situ, the time complexity of O (n ^ 2), so it is relatively low efficiency in a large list.
However, the algorithm is known for its simplicity, and in some cases, it has performance advantages over more complex algorithms, especially when the auxiliary memory limited time.

Selection Sort input list divided into two parts: ordered sub-lists (the front end of the list), and the sub-list to be sorted. Initially, the sorted sub-list is empty, unordered sub-list is the entire list. Algorithm by looking at the list to be sorted sub-smallest element, which is to be exchanged with the leftmost element ordering, and ordered sub-list to the right border of an element to continue.

5.1 parsing algorithm steps

  • First, find the smallest sequence of unsorted (large) element, the starting position is stored in the sorted sequence
  • From the remaining unsorted then continue to look for the minimum element (large) element, and then into the end of the sorted sequence.
  • The second step is repeated until all the elements are sorted completed.

5.2 graphic

Selection Sort
Here Insert Picture Description

5.3 Code

def select_sort(alist):
    for i in range(len(alist)):
        min_num = i
        for j in range(i+1, len(alist)):
            if alist[j] < alist[min_num]:
                min_num = j
        alist[i], alist[min_num] = alist[min_num], alist[i]
    return alist

5.4 parsed

  1. Loop minimum is found never sorted list (already sorted list, and the last size comparison value), and the last value in the list sorted exchange.
  2. The initial list to find a first minimum value, set the default initial value, it is necessary outer loop len (alist)
  3. The default setting handled as the minimum value of the outer loop variable i
  4. Select the minimum inner loop (the initial value and the minimum comparative) elements, the minimum value is updated if found subscript, round the loop until the end of the initial value and the minimum value of the exchange; round until the end of the loop if not found, start the next round outside the loop.

6. insertion sort

Insertion Sort is a simple sorting algorithm requires only one pass through the array to generate the final ranking. Its efficiency is lower than a large list of more advanced algorithms, however, it has the following advantages:
a, simple, a few lines of code to complete.
Second, the small data set is very effective (relatively).
Three, (^ 2 n) algorithm is more efficient than other simple O in practice.
Fourth, the adaptation, when the input of each element from its end position is not more than k, the time complexity of only O (kn).
Five stable, does not change the relative order of elements having values equal.
Sixth, the low spatial complexity, only O (1).
Seven online algorithm can sort while being read, do not need to read the entire array.

6.1-parsing algorithm steps

  • The first element to be considered as a first ordered sequence of an ordered sequence, the second element is the last element as unsorted sequence.
  • Unsorted sequence from start to finish sequentially scanned, the scanning element is inserted into an appropriate position of each ordered sequence. (If the elements to be inserted in an ordered sequence of elements are equal, the elements to be inserted is inserted into the back of the equal element.)

6.2 graphic

insert
Here Insert Picture Description

6.3 Code

def insert_sort(alist):
    for i in range(1, len(alist)):
        for j in range(i, 0, -1):
            if alist[j] < alist[j-1]:
                alist[j], alist[j-1] = alist[j-1], alist[j]
            else:
                break
    return alist

6.4 parsed

Abstract analysis:

Or when we play, and how the fastest sorting cards?

  1. Our first card to the initial value
  2. First cycle determination, determines whether the second than the first card Da, then the switch sequence is no, there is no fixed position, out of round loop.
  3. The second round of the cycle, the third card is determined after Queen than the second, then the switch sequence is no, there is no fixed location; in comparison with the first card, if the card 1 is not large, the sequence continues to the exchange, there are the position does not move. Out of the current round of circulation.
  4. So, after the n 1-cycle wheel to obtain a final result.

time complexity:

best:O(n)

worst:O(n^2)

The key is to code else, break. When the list is in ascending or descending order has, and does not satisfy the condition comparing two exchange element size, indicating that the element larger or smaller than the previous element, since the front element larger than all the elements before it or small, they can all out of this cycle. After n cycles of equivalent, only performed once each cycle BREAK, so the optimal time complexity is O (n).

7. merge sort

Merge sort is an efficient, versatile, relatively sorting algorithm based on the algorithm uses the idea of ​​partition, the larger question of the sort attributed to solve on a smaller scale.

Merge sort the following steps:

First, the unordered list into two elements in the same number of sub-arrays.

Second, ordering two sub-arrays, and then merge them.

7.1 definitions

Merge sort is the divide and conquer algorithm, the first points, (comparative composition before descending order) in combination. The main two steps.

  1. Dividing continuous unsorted list until there are N sublists, each sublist has an "unsorted" element, N is the number of elements of the original array.
  2. The combined repeated, i.e. once the two sub-lists are combined to generate a new sub-list sorted until fully incorporated into all of the elements in a sorted array.

7.2 graphic

Merger
Here Insert Picture Description

7.3 code implementation

# coding:utf-8
def merge_sort(alist):
    num = len(alist)
    if num == 1:
        return alist

    mid = num // 2
    left_li = merge_sort(alist[:mid])
    right_li = merge_sort(alist[mid:])

    left_pointer, right_pointer = 0, 0
    result = []

    while left_pointer < len(left_li) and right_pointer < len(right_li):
        if left_li[left_pointer] < right_li[right_pointer]:
            result.append(left_li[left_pointer])
            left_pointer += 1
        else:
            result.append(right_li[right_pointer])
            right_pointer += 1
    result += left_li[left_pointer:]
    result += right_li[right_pointer:]
    return result


result2 = merge_sort([1, 8, 7, 3, 5, 6, 4, 2, 9])
print(result2)

7.4 parsed

  1. Split: until the individual split independent result, when an individual length 1, to merge.
  2. The result of the global variable to accept the merger
  3. The left pointer and the right pointer setting an initial value of 0
  4. Analyzing the set cycle length (and the condition) about the list of pointers after the conditions must be less than about split. (Preventing list pointer value exceeds the index range), when the condition is not met out of the loop.
  5. Merge: The pointer value of about the size of the list comparison. Small first stored global variables within the combined result, and the corresponding list pointer + = 1 Split
  6. When a value for a list of all the memory split merged result, the split list pointer value reaches the maximum index value. Another split list, certainly when large size in comparison steps than 5 combined result value has been stored, and the list is ordered state split, it can be directly on the basis of the results have been combined, together with the demolition list pointer points to the last value of all elements. (Note: when a pointer value of a list of the maximum resolution is reached, the pointer value takes the final result is an empty list, for example, a = [0,1,2,3], and a [4:] values ​​are null list)
  7. Back to Results

time complexity:

best:O(n log(n))

worst:O(n log(n))

7.5 code running steps

def merge_sort([1, 8, 7, 3, 5, 6, 4, 2]):
    mid = 4
    left_li = def merge_sort([1, 8, 7, 3]):
        mid = 2
        left_li = def merge_sort([1, 8]):
            mid = 1
            left_li = def merge_sort([1]):
                return alist  # 到这里第7含的merge函数执行完毕(得到结果left_li=[1]),第7行的函数知识第5含函数的一含代码,继续向下执行.
            right_li = def merge_sort([8]): 
                return alist  # 同第8行代码一样,第9含的函数也是第5含代码函数的一行代码,得到结果right_li=[8]),继续向下执行.
            # 左右指针=0
            # result = []
            # 循环判断
                result= [1], 左指针 = 1, 右指针 = 0
            result = [1] + [] = [1]
            result = [1] + [8] = [1,8]
            return result # 到这里第5行代码执行完毕,得到结果left_li = [1, 8]
        right_li = def merge_sort([7, 3]):
            mid = 1
            left_li = [7]
            right_li = [3]
            # 左右指针=0
            # result = []
            # 循环判断
                result= [3], 右指针 = 1, 左指针 = 0
            result = [3] + [] = [3]
            result = [3] + [7] = [3,7]
            return result # 到这里第18行代码执行完毕,得到结果right_li = [3, 7]
        left_li = [1, 8]
        right_li = [3, 7]
        # 左右指针=0
        # result = []
        # 循环判断
        result= [1], 左指针 = 1, 右指针 = 0
        result= [1,3], 右指针 = 1, 左指针 = 1
        result= [1,3,7], 右指针 = 2, 左指针 = 1
        result = [1,3,7] + [8] = [1,3,7,8]
        result = [1,3,7,8] + [] = [1,3,7,8]
        return result # 到这里第3行代码执行完毕,得到结果left_li = [1,3,7,8]
    right_li = def merge_sort([5,6,4,2]):
        # 执行步骤同第4行到第39行代码一样.
         return result # 到这里第40行代码执行完毕,得到结果right_li = [2,4,5,6]
    left_li = [1,3,7,8]
    right_li = [2,4,5,6]
    # 左右指针=0
    # result = []
    # 循环判断
    result= [1], 左指针 = 1, 右指针 = 0
    result= [1,2], 右指针 = 1, 左指针 = 1
    result= [1,2,3], 左指针 = 2, 右指针 = 1
    result= [1,2,3,4], 左指针 = 2, 右指针 = 2
    result= [1,2,3,4,5], 右指针 = 3, 左指针 = 2
    result= [1,2,3,4,5,6], 右指针 = 4, 左指针 = 2
    # 到这里右指针 = 4, 左指针 = 2, 不满足循环条件,
    result = [1,2,3,4,5,6] + [7,8] = [1,2,3,4,5,6,7,8]
    result = [1,2,3,4,5,6,7,8] + [] = [1,2,3,4,5,6,7,8]
    return result # 到这里第1行代码执行完毕,得到结果result = [1,2,3,4,5,6,7,8]

8. Quick Sort

8.1 definitions

Quick sort is also a divide-and-conquer algorithms such as merge sort. Although it is a little complicated, but in most standard implementation, which is performed faster than merge sort, and rarely achieved the worst-case complexity of O (n). It has three main steps:

  1. Select an element from the array, referred to pivot.
  2. Sort the array, so that all the elements are located before the pivot is smaller than the pivot, and the pivot is greater than all the values ​​for the elements are positioned pivot (equal values ​​may be moved in any direction). This step is often referred to partition.
  3. The above procedure is applied recursively sub-arrays before and after the pivot.
    The basic situation is recursive array of size 0 or 1, which are arranged by definition, there is no need to sort them.

8.2 graphic

Fast row
Fast row 2

8.3 code implementation

Mode 1:

def quick_sort(alist):
    if len(alist) < 2:  # 递归出口,当数组是空数组或者只有一个元素的数组都是有序的。
        return alist
    else:
        pivot_index = 0
        pivot = alist[pivot_index]
        less_part = [i for i in alist[pivot_index+1:] if i <= pivot]
        great_part = [i for i in alist[pivot_index+1:] if i > pivot]
        return quick_sort(less_part) + [pivot] + quick_sort(great_part)

Mode 2 :

def quick_sort(li, start, end):
    if start >= end:
        return

    l_pointer = start
    r_pointer = end
    pivot = li[l_pointer]

    while l_pointer < r_pointer:
        while l_pointer < r_pointer and li[r_pointer] >= pivot:
            r_pointer -= 1
        li[l_pointer], li[r_pointer] = li[r_pointer],  li[l_pointer]

        while l_pointer < r_pointer and li[l_pointer] < pivot:
            l_pointer += 1
        li[l_pointer], li[r_pointer] = li[r_pointer],  li[l_pointer]

    li[l_pointer] = pivot

    quick_sort(li, start, l_pointer - 1)
    quick_sort(li, l_pointer + 1, end)

Guess you like

Origin www.cnblogs.com/yblackd/p/12470766.html