Python implements several classic sorting and searching algorithms

Table of contents

Sorting Algorithm

Bubble Sort

principle

Code

selection sort

principle

Code

insertion sort

principle

Implementation code

quick sort

principle

Implementation code

merge sort

principle

Implementation code

search algorithm

linear search

binary search

principle

Implementation code

interpolation lookup

principle

Implementation code

Fibonacci lookup

principle

Implementation code


Sorting Algorithm

Bubble Sort

principle

Bubble sort is a basic sorting algorithm. The basic idea is to make smaller elements gradually "float" to the top of the array and larger elements "sink" to the bottom of the array by comparing and exchanging adjacent elements. Specifically, the algorithm flow of bubble sorting is as follows:

  1. Compares two adjacent elements. If the first is bigger than the second, swap their positions, otherwise don't.
  2. Do the same for each pair of adjacent elements, from the first pair to the last pair, so that after a round, the last element will be the largest number.
  3. Repeat the above steps for all elements except the last one.
  4. Continue repeating the above steps for fewer and fewer elements each time until there are no pairs of numbers to compare.

Bubble sort is a stable sorting algorithm because it does not change the relative order of the same elements. However, due to its high time complexity, it is not suitable for sorting large-scale data.

Code

def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        for j in range(n-i-1):
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
    return arr

selection sort

principle

Selection sort is a basic sorting algorithm. The basic idea is to find the smallest (largest) element among the unsorted elements, store it at the beginning of the sorted sequence, and then continue to find the smallest (largest) element from the remaining unsorted elements and put it in the sorted sequence the end of the sequence. Specifically, the algorithm flow of selection sort is as follows:

  1. Find the smallest (largest) element in the unsorted sequence and store it at the beginning of the sorted sequence.
  2. Then continue to find the smallest (largest) element from the remaining unsorted elements, and put it at the end of the sorted sequence.
  3. Repeat the second step until all elements are sorted.

Selection sort is an unstable sorting algorithm because it may change the relative order of the same elements. However, the time complexity of selection sorting is O(n^2), and the space complexity is O(1), which is slightly faster than bubble sorting, but it is still not efficient enough for sorting large-scale data.

Code

def selection_sort(arr):
    n = len(arr)
    for i in range(n):
        min_idx = i
        for j in range(i+1, n):
            if arr[j] < arr[min_idx]:
                min_idx = j
        arr[i], arr[min_idx] = arr[min_idx], arr[i]
    return arr

insertion sort

principle

Insertion sort is a basic sorting algorithm. The basic idea is to insert unsorted elements into the sorted sequence one by one, resulting in a new, sorted sequence. Specifically, the algorithm flow of insertion sort is as follows:

  1. Starting with the first element, the element can be considered a sorted section.
  2. Fetch the next element and scan from back to front in the sorted sequence of elements.
  3. If the element (sorted) is larger than the new element, move the element to the next position.
  4. Repeat step 3 until you find a position where the sorted element is less than or equal to the new element.
  5. After inserting a new element at that position.
  6. Repeat steps 2~5 until sorting is complete.

Insertion sort is a stable sorting algorithm because it does not change the relative order of the same elements. The time complexity of insertion sorting is O(n^2), and the space complexity is O(1), which is slightly faster than bubble sorting and selection sorting, but it is still not efficient enough for sorting large-scale data.

Implementation code

def insertion_sort(arr):
    n = len(arr)
    for i in range(1, n):
        key = arr[i]
        j = i-1
        while j >= 0 and key < arr[j]:
            arr[j+1] = arr[j]
            j -= 1
        arr[j+1] = key
    return arr

quick sort

principle

Quicksort is a basic sorting algorithm. The basic idea is to divide the records to be sorted into two independent parts through a sorting pass, and the keywords of one part of the records are smaller than the keywords of the other part of the records, and then continue to sort the two parts of the records respectively, so as to achieve The purpose of ordering the entire sequence. Specifically, the algorithm flow of quick sort is as follows:

  1. Pick an element from the sequence, called the "pivot".
  2. Rearrange the sequence so that all elements smaller than the "base" are placed on the left of the "base", all elements greater than the "base" are placed on the right of the "base", and the same elements can be placed on any side. After this partition is over, the "baseline" is in the middle of the sequence. This is called a partition operation.
  3. Recursively, repeat steps 1 and 2 for the subsequence on the left and the subsequence on the right of the "baseline" until there is only one element in each subsequence.

Quicksort is an unstable sorting algorithm because it may change the relative order of the same elements. The time complexity of quicksort is O(nlogn), and the space complexity is O(logn). In most cases, quicksort is an efficient sorting algorithm, but in the worst case, the time complexity is O( n^2), special handling is required to avoid this.

Implementation code

def quick_sort(arr):
    if len(arr) <= 1:
        return arr
    else:
        pivot = arr[0]
        left = []
        right = []
        for i in range(1, len(arr)):
            if arr[i] < pivot:
                left.append(arr[i])
            else:
                right.append(arr[i])
        return quick_sort(left) + [pivot] + quick_sort(right)

merge sort

principle

Merge sort is a divide-and-conquer algorithm that divides the array to be sorted into two parts, then sorts the two parts separately, and finally merges the sorted two parts into an ordered array.

The specific implementation process is as follows:

1. Divide the array to be sorted into two parts from the middle, namely the left half and the right half.

2. Merge and sort the left half and the right half respectively until only one element remains in each part.

3. Merge the sorted left half and right half into an ordered array.

4. Repeat steps 2 and 3 until the entire array is sorted.

The time complexity of merge sort is O(nlogn), it is a stable sorting algorithm.

The space complexity of merge sort is O(n), where n is the length of the array to be sorted. Merge sort requires additional space to store intermediate results during the merge process, which need to occupy the same size space as the original array. Therefore, the space complexity of merge sort is O(n).

Implementation code

def merge_sort(arr):
    if len(arr) <= 1:
        return arr
    else:
        mid = len(arr) // 2
        left = arr[:mid]
        right = arr[mid:]

        left = merge_sort(left)
        right = merge_sort(right)

        return merge(left, right)

def merge(left, right):
    result = []
    i = j = 0
    while i < len(left) and j < len(right):
        if left[i] < right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1
    result += left[i:]
    result += right[j:]
    return result

search algorithm

linear search

def linear_search(arr, x):
    for i in range(len(arr)):
        if arr[i] == x:
            return i
    return -1

binary search

principle

Binary Search (Binary Search) is a search algorithm based on comparing the target value and the middle element of the array. Its basic idea is: during the search process, the search range is continuously narrowed until the target element is found or the search range is empty.

The specific implementation process is as follows:

1. Sort the array to be searched in ascending order of element size.

2. Set left and right boundaries of the search range. Initially, left is the subscript of the first element of the array, and right is the subscript of the last element of the array.

3. Calculate the subscript mid of the middle element, mid = (left + right) / 2.

4. Compare the size of the target element target and the middle element arr[mid].

a.如果target等于arr[mid],则查找成功,返回mid。

b.如果target小于arr[mid],则在左半部分继续查找,将右边界right设为mid-1。

c.如果target大于arr[mid],则在右半部分继续查找,将左边界left设为mid+1。

5. Repeat steps 3 and 4 until the target element is found or the search range is empty.

If the target element does not exist in the array, the final search result will return -1.

The time complexity of binary search is O(log n), where n is the length of the array to be searched.

Implementation code

def binary_search(arr, x):
    low = 0
    high = len(arr) - 1
    while low <= high:
        mid = (low + high) // 2
        if arr[mid] == x:
            return mid
        elif arr[mid] < x:
            low = mid + 1
        else:
            high = mid - 1
    return -1

interpolation lookup

principle

Interpolation Search (Interpolation Search) is an optimization algorithm based on binary search, which quickly locates the position of the target element by estimating the search range. In the interpolation search, we estimate the approximate position of the target element in the search range according to the ratio between the target element and the maximum and minimum values ​​of the search range, then adjust the search range according to the estimation result, and finally find the target element.

The specific implementation process is as follows:

1. Sort the array to be searched in ascending order of element size.

2. Set left and right boundaries of the search range. Initially, left is the subscript of the first element of the array, and right is the subscript of the last element of the array.

3. Calculate the estimated position pos of the target element in the search range, pos = left + (right - left) * (target - arr[left]) / (arr[right] - arr[left]).

4. Compare the size of the target element target and the element arr[pos] at the estimated position pos.

a.如果target等于arr[pos],则查找成功,返回pos。

b.如果target小于arr[pos],则在左半部分继续查找,将右边界right设为pos-1。

c.如果target大于arr[pos],则在右半部分继续查找,将左边界left设为pos+1。

5. Repeat steps 3 and 4 until the target element is found or the search range is empty.

If the target element does not exist in the array, the final search result will return -1.

The time complexity of interpolation search is O(log log n)~O(log n), where n is the length of the array to be searched. When the elements in the array are evenly distributed, the efficiency of interpolation search is very high, but when the elements are not evenly distributed, the efficiency of interpolation search may not be as good as binary search.

Implementation code

def interpolation_search(arr, x):
    low = 0
    high = len(arr) - 1
    while low <= high and x >= arr[low] and x <= arr[high]:
        pos = low + ((x - arr[low]) * (high - low)) // (arr[high] - arr[low])
        if arr[pos] == x:
            return pos
        elif arr[pos] < x:
            low = pos + 1
        else:
            high = pos - 1
    return -1

Fibonacci lookup

principle

Fibonacci Search is a search algorithm based on the golden section principle, which uses the ratio of two adjacent numbers in the sequence to approximate the golden section ratio, and quickly locates the position of the target element. In the Fibonacci search, we first use the Fibonacci sequence to generate an increasing subscript sequence, and then locate the target element according to the subscript sequence.

The specific implementation process is as follows:

1. Sort the array to be searched in ascending order of element size.

2. Use the Fibonacci sequence to generate an increasing subscript sequence fib, so that fib[k] >= n, where n is the length of the array to be searched.

3. Set the left and right boundaries of the search range, left and right. Initially, left is the subscript of the first element of the array, and right is the subscript of the last element of the array.

4. Calculate the sum f of the k-1th number and the k-2th number in the Fibonacci sequence, so that f is exactly greater than or equal to the length of the current search range, that is, f = fib[k-1] + fib[k -2] >= right - left + 1.

5. Divide the search range into two parts according to f, the length of the first half is fib[k-2], and the length of the second half is fib[k-1].

6. Compare the size of the target element target and the last element arr[left+fib[k-2]-1] in the first half.

a.如果target等于arr[left+fib[k-2]-1],则查找成功,返回left+fib[k-2]-1。

b.如果target小于arr[left+fib[k-2]-1],则在前半部分继续查找,将右边界right设为left+fib[k-2]-2,同时将k减小1,f减小fib[k-1]。

c.如果target大于arr[left+fib[k-2]-1],则在后半部分继续查找,将左边界left设为left+fib[k-2],同时将k减小2,f减小fib[k-2]和fib[k-1]。

7. Repeat steps 4 to 6 until the target element is found or the search range is empty.

If the target element does not exist in the array, the final search result will return -1.

The time complexity of Fibonacci search is O(log n), where n is the length of the array to be searched.

Implementation code

def fibonacci_search(arr, x):
    n = len(arr)
    fib2 = 0
    fib1 = 1
    fib = fib2 + fib1
    while fib < n:
        fib2 = fib1
        fib1 = fib
        fib = fib2 + fib1
    offset = -1
    while fib > 1:
        i = min(offset+fib2, n-1)
        if arr[i] < x:
            fib = fib1
            fib1 = fib2
            fib2 = fib - fib1
            offset = i
        elif arr[i] > x:
            fib = fib2
            fib1 = fib1 - fib2
            fib2 = fib - fib1
        else:
            return i
    if fib1 and offset < n-1 and arr[offset+1] == x:
        return offset + 1
    return -1

Guess you like

Origin blog.csdn.net/L888666Q/article/details/131123278