Top Ten Classic Sorting Algorithms [Quick Understanding]


1. Algorithm classification

The ten common sorting algorithms can be divided into two broad categories:

  • Compare class ordering:
    • Determine the relative order of elements by comparison
    • Because its time complexity cannot be broken through O(nlogn), it is also called nonlinear time comparison sorting.
  • Non-comparative sorting:
    • Relative ordering of elements is not determined by comparison
    • It can break through the time lower bound of comparison-based sorting and run in linear time, so it is also called linear-time non-comparative sorting.
      insert image description here


2. Overview of classic sorting algorithms

The ten classic algorithms are:

  • bubble sort

    • Bubble Sort (Bubble Sort) is an exchange -based sort
    • Each time you traverse the elements that need to be sorted, compare the size of the adjacent two elements in turn . If the previous element is greater than the latter element, exchange the two to ensure that the last number must be the largest (assuming that it is sorted from small to large
    • That is, the last element has been sorted, and the next round only needs to ensure the order of the first n-1 elements .

    insert image description here

Process demonstration: array to be sorted {5, 4, 7, 1, 6, 2}, sorted in ascending order

Algorithm steps:

  1. Compare adjacent elements . If the first is greater than the second, swap them both;
  2. Do the same for each pair of adjacent elements , from the first pair at the beginning to the last pair at the end, so the element at the end should be the largest number;
  3. Repeat the above steps for all elements except the last one;
  4. Repeat steps 1~3 until sorting is complete.

  • selection sort
    • The bubble sort mentioned above is to determine the last element in each round of comparison, and the middle process is constantly exchanged.
    • The selection sort is to select the smallest element among the remaining elements each time , and exchange it with the element at the current index position until all the index positions are selected.

insert image description here
[Algorithm steps] nThe direct selection and sorting of a record can n-1obtain an ordered result through direct selection and sorting. The specific algorithm is described as follows:

  1. Initial state: the unordered area is R[1..n], the ordered area is empty;
  2. At the beginning of the first isorting ( ), the current ordered area and unordered area are and i=1,2,3…n-1respectively . R[1..i-1]R(i..n)
    • This sorting process selects the record with the smallest key from the current unordered area , and exchanges it with the first record R R[k]in the unordered area1
    • Make R[1..i]and respectively become a new ordered area withR[i+1..n) the number of records increased by 1 and a new disordered area with the number of records decreased by 1 ;
  3. n-1At the end of the pass, the array is sorted.

  • insertion sort
    • Selection sort is to select the smallest one each time and put it behind the array that has been arranged
    • The insertion sort is to select an element in turn and insert it into the middle of the previously sorted array to ensure that it is in the correct position.
    • Of course, this requires constant movement of the sorted array .

insert image description here
[Algorithm steps] Generally speaking, insertion sorting is implemented on arrays using in-place. The specific algorithm is described as follows:

  1. Starting from the first element, the element can be considered sorted;
  2. Take out the next element and scan from back to front in the sorted element sequence;
  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 the 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.

  • Hill sort
    • Shell's Sort, also known as " Diminishing Increment Sort", is a more efficient and improved version of insertion sort.
    • The pain point of insertion sort is that no matter whether it is mostly ordered or not, elements will be compared. If the minimum number is at the end of the array, it will be more laborious to move it to the head of the array.
    • Hill sorting is to use jump grouping in the array, group according to a certain incremental gap, divide it into several groups, and perform insertion sorting on each group .
      • Then gradually reduce the incremental gap
      • Insertion sort is performed on each group, and the process is repeated until the increment is 1.

insert image description here
[Algorithm steps] First divide the entire record sequence to be sorted into several subsequences for direct insertion sorting . The specific algorithm description:

  1. Choose a sequence of increments t1,t2,…,tkwhere ti > tj;tk = 1
  2. According to the number of incremental sequences k, sort the sequence ktimes;
  3. For each sorting, according to the corresponding increment ti, the column to be sorted is divided into several msubsequences of length , and direct insertion sorting is performed on each subtable.
    • Only when the increment factor is 1, the entire sequence is treated as a table, and the length of the table is the length of the entire sequence.

  • quick sort
    • Quick sort is more interesting. Select a number in the array as the reference number, sort in one pass, and divide the array into two parts
      • Some of them are less than/equal to the benchmark
      • The other part is greater than/equal to the benchmark number.
    • Then continue to sort the left and right parts of the benchmark number until the array is in order. This embodies the idea of ​​​​divide and conquer , which is also applied to the strategy of digging holes and filling numbers.

insert image description here
[Algorithm steps] Quick sort uses divide and conquer method to divide a string (list) into two sub-strings (sub-lists). The specific algorithm is described as follows:

  1. Pick an element from the sequence, called the "pivot" ;
  2. Reorder the sequence, all elements smaller than the reference value are placed in front of the reference value , and all elements larger than the reference value are placed behind the reference value (the same number can go to either side).
  3. After this partition exits, the benchmark is in the middle of the sequence . This is called a partition operation ;
  4. Recursively sort subarrays with elements less than the base value and subarrays with elements greater than the base value .

  • merge sort
    • The previous quick sort embodies the idea of ​​​​divide and conquer, but it is not typical
    • Merge sort is a very typical divide and conquer strategy . The general idea of ​​merging is to split the array first, then split ...
    • It is divided into one element, and then merged and sorted in pairs to achieve partial order, and merged continuously until the array is all combined again.

insert image description here
Algorithm steps

  1. nsplits the input sequence of length into two n/2subsequences of length ;
  2. Use merge sort for the two subsequences respectively ;
  3. Merges two sorted subsequences into a final sorted sequence.

  • bucket sort
    • Bucket sorting refers to using multiple buckets to store elements, and each bucket has a storage range
    • First put the elements into each bucket according to the range, and each bucket is a sub-array, then sort each sub-array , and finally merge the sub-arrays to become the final ordered array.
    • This is actually very similar to counting sort, except that counting sort has only one element in each bucket, and the value stored in the bucket is the number of occurrences of the element.

insert image description here
Algorithm steps

  1. Set a quantitative array as an empty bucket ;
  2. Traverse the input data and put the data one by one into the corresponding bucket ;
  3. Sort each bucket that is not empty ;
  4. Concatenate sorted data from non-empty buckets .

  • heap sort
    • Heap sorting is a sorting algorithm designed using a large top heap or a small top heap . It is a selection sort.
    • A heap is a complete binary tree :
      • Big top heap: The value of each node is greater than or equal to the value of its left and right child nodes .
      • Small top heap: the value of each node is less than or equal to the value of its left and right child nodes .

insert image description here
Algorithm steps:

  1. Build the initial sequence of keywords (R1,R2….Rn)to be sorted into a large top heap , which is the initial unordered area;
  2. Exchange the top element of the heapR[1] with the last element R[n], and get a new unordered area (R1,R2,……Rn-1)and a new ordered area at this time (Rn), and satisfy R[1,2…n-1]<=R[n];
  3. Since the new heap top after the exchange R[1]may violate the nature of the heap, it is necessary to adjust the current unordered area (R1,R2,……Rn-1)to a new heap , and then R[1]exchange the last element with the unordered area again to obtain a new unordered area (R1,R2….Rn-2)and a new ordered area (Rn-1,Rn).
  4. Repeat this process until the number of elements in the sorted area is n-1, then the entire sorting process is complete.

  • counting sort
    • Counting sort, not based on comparison, but on count
    • It is more suitable for cases where the element values ​​are similar and are integers

insert image description here
Algorithm steps

  1. Find the largest and smallest elements in the array to be sorted ;
  2. Count the number ofi occurrences of elements with each value in the array , and store them in the first item of array C ;i
  3. Accumulate all counts (starting Cfrom the first element, each item is added to the previous item);
  4. Fill the target array in reverse: put each element i in the item of the new array , and subtract 1 C(i)for each element placed .C(i)

  • radix sort
    • Cardinality sorting is special in that it can only be used for integer (natural number) sorting , and it is not based on comparison .
    • The principle is to divide the integer into different numbers according to the digits, and sort them step by step according to the value of each digit .
    • What is the high bit, such as 81, 1 is the low bit, and 8 is the high bit.
    • Divided into high-order priority and low-order priority , comparing the high-order first is the high-order priority, and comparing the low-order first is the low-order priority.

insert image description here

Algorithm steps:

  1. Obtain the maximum number in the array and obtain the number of digits ;
  2. arrFor the original array, each bit is taken from the lowest bit to form radixan array;
  3. radixCounting and sorting ( using counting sorting is suitable for small range numbers);


3. Algorithm complexity

Common sorting algorithm complexity
insert image description here
insert image description here

Related concepts

  • Stable : If a is originally in front of b, and a=b, a is still in front of b after sorting .
  • Unstable : If a is originally in front of b, and a=b, a may appear behind b after sorting .
  • Time complexity: The total number of operations on sorted data . It reflects the regularity of the number of operations when n changes.
  • Space complexity: refers to the measurement of the storage space required by the algorithm when it is executed in the computer , and it is also a function of the data size n


4. Code implementation

  • Bubble Sort
function bubbleSort(arr) {
    
    
    var len = arr.length;
    for (var i = 0; i < len - 1; i++) {
    
    
        for (var j = 0; j < len - 1 - i; j++) {
    
    
            if (arr[j] > arr[j+1]) {
    
            // 相邻元素两两对比
                var temp = arr[j+1];        // 元素交换
                arr[j+1] = arr[j];
                arr[j] = temp;
            }
        }
    }
    return arr;
}

insert image description here


  • Selection Sort
function selectionSort(arr) {
    
    
    var len = arr.length;
    var minIndex, temp;
    for (var i = 0; i < len - 1; i++) {
    
    
        minIndex = i;
        for (var j = i + 1; j < len; j++) {
    
    
            if (arr[j] < arr[minIndex]) {
    
         // 寻找最小的数
                minIndex = j;                 // 将最小数的索引保存
            }
        }
        temp = arr[i];
        arr[i] = arr[minIndex];
        arr[minIndex] = temp;
    }
    return arr;
} 

insert image description here


  • Insertion Sort
function insertionSort(arr) {
    
    
    var len = arr.length;
    var preIndex, current;
    for (var i = 1; i < len; i++) {
    
    
        preIndex = i - 1;
        current = arr[i];
        while (preIndex >= 0 && arr[preIndex] > current) {
    
    
            arr[preIndex + 1] = arr[preIndex];
            preIndex--;
        }
        arr[preIndex + 1] = current;
    }
    return arr;
}

insert image description here


  • Shell sort (Shell Sort)
function shellSort(arr) {
    
    
    var len = arr.length;
    for (var gap = Math.floor(len / 2); gap > 0; gap = Math.floor(gap / 2)) {
    
    
        // 注意:这里和动图演示的不一样,动图是分组执行,实际操作是多个分组交替执行
        for (var i = gap; i < len; i++) {
    
    
            var j = i;
            var current = arr[i];
            while (j - gap >= 0 && current < arr[j - gap]) {
    
    
                 arr[j] = arr[j - gap];
                 j = j - gap;
            }
            arr[j] = current;
        }
    }
    return arr;
}

insert image description here


  • Merge Sort
function mergeSort(arr) {
    
    
    var len = arr.length;
    if (len < 2) {
    
    
        return arr;
    }
    var middle = Math.floor(len / 2),
        left = arr.slice(0, middle),
        right = arr.slice(middle);
    return merge(mergeSort(left), mergeSort(right));
}
 
function merge(left, right) {
    
    
    var result = [];
 
    while (left.length>0 && right.length>0) {
    
    
        if (left[0] <= right[0]) {
    
    
            result.push(left.shift());
        } else {
    
    
            result.push(right.shift());
        }
    }
 
    while (left.length)
        result.push(left.shift());
 
    while (right.length)
        result.push(right.shift());
 
    return result;
}

insert image description here


  • Quick sort (Quick Sort)
function quickSort(arr, left, right) {
    
    
    var len = arr.length,
        partitionIndex,
        left = typeof left != 'number' ? 0 : left,
        right = typeof right != 'number' ? len - 1 : right;
 
    if (left < right) {
    
    
        partitionIndex = partition(arr, left, right);
        quickSort(arr, left, partitionIndex-1);
        quickSort(arr, partitionIndex+1, right);
    }
    return arr;
}
 
function partition(arr, left ,right) {
    
         // 分区操作
    var pivot = left,                      // 设定基准值(pivot)
        index = pivot + 1;
    for (var i = index; i <= right; i++) {
    
    
        if (arr[i] < arr[pivot]) {
    
    
            swap(arr, i, index);
            index++;
        }       
    }
    swap(arr, pivot, index - 1);
    return index-1;
}
 
function swap(arr, i, j) {
    
    
    var temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

insert image description here


  • Heap Sort
var len;    // 因为声明的多个函数都需要数据长度,所以把len设置成为全局变量
 
function buildMaxHeap(arr) {
    
       // 建立大顶堆
    len = arr.length;
    for (var i = Math.floor(len/2); i >= 0; i--) {
    
    
        heapify(arr, i);
    }
}
 
function heapify(arr, i) {
    
         // 堆调整
    var left = 2 * i + 1,
        right = 2 * i + 2,
        largest = i;
 
    if (left < len && arr[left] > arr[largest]) {
    
    
        largest = left;
    }
 
    if (right < len && arr[right] > arr[largest]) {
    
    
        largest = right;
    }
 
    if (largest != i) {
    
    
        swap(arr, i, largest);
        heapify(arr, largest);
    }
}
 
function swap(arr, i, j) {
    
    
    var temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}
 
function heapSort(arr) {
    
    
    buildMaxHeap(arr);
 
    for (var i = arr.length - 1; i > 0; i--) {
    
    
        swap(arr, 0, i);
        len--;
        heapify(arr, 0);
    }
    return arr;
}

insert image description here


  • Counting Sort
function countingSort(arr, maxValue) {
    
    
    var bucket = new Array(maxValue + 1),
        sortedIndex = 0;
        arrLen = arr.length,
        bucketLen = maxValue + 1;
 
    for (var i = 0; i < arrLen; i++) {
    
    
        if (!bucket[arr[i]]) {
    
    
            bucket[arr[i]] = 0;
        }
        bucket[arr[i]]++;
    }
 
    for (var j = 0; j < bucketLen; j++) {
    
    
        while(bucket[j] > 0) {
    
    
            arr[sortedIndex++] = j;
            bucket[j]--;
        }
    }
 
    return arr;
}

insert image description here


  • Bucket Sort
function bucketSort(arr, bucketSize) {
    
    
    if (arr.length === 0) {
    
    
      return arr;
    }
 
    var i;
    var minValue = arr[0];
    var maxValue = arr[0];
    for (i = 1; i < arr.length; i++) {
    
    
      if (arr[i] < minValue) {
    
    
          minValue = arr[i];                // 输入数据的最小值
      } else if (arr[i] > maxValue) {
    
    
          maxValue = arr[i];                // 输入数据的最大值
      }
    }
 
    // 桶的初始化
    var DEFAULT_BUCKET_SIZE = 5;            // 设置桶的默认数量为5
    bucketSize = bucketSize || DEFAULT_BUCKET_SIZE;
    var bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1;  
    var buckets = new Array(bucketCount);
    for (i = 0; i < buckets.length; i++) {
    
    
        buckets[i] = [];
    }
 
    // 利用映射函数将数据分配到各个桶中
    for (i = 0; i < arr.length; i++) {
    
    
        buckets[Math.floor((arr[i] - minValue) / bucketSize)].push(arr[i]);
    }
 
    arr.length = 0;
    for (i = 0; i < buckets.length; i++) {
    
    
        insertionSort(buckets[i]);                      // 对每个桶进行排序,这里使用了插入排序
        for (var j = 0; j < buckets[i].length; j++) {
    
    
            arr.push(buckets[i][j]);                     
        }
    }
 
    return arr;
}

insert image description here


  • Radix Sort (Radix Sort)
var counter = [];
function radixSort(arr, maxDigit) {
    
    
    var mod = 10;
    var dev = 1;
    for (var i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) {
    
    
        for(var j = 0; j < arr.length; j++) {
    
    
            var bucket = parseInt((arr[j] % mod) / dev);
            if(counter[bucket]==null) {
    
    
                counter[bucket] = [];
            }
            counter[bucket].push(arr[j]);
        }
        var pos = 0;
        for(var j = 0; j < counter.length; j++) {
    
    
            var value = null;
            if(counter[j]!=null) {
    
    
                while ((value = counter[j].shift()) != null) {
    
    
                      arr[pos++] = value;
                }
          }
        }
    }
    return arr;
}

insert image description here

Guess you like

Origin blog.csdn.net/weixin_43338969/article/details/129324970
Recommended