Notes on ten classic sorting algorithms

Keywords: Algorithm

Related concepts

stability

  • Stable: if a was in front of b and a=b, a will still be in front of b after sorting.
  • Unstable: if a was originally in front of b and a=b, a may appear after b after sorting.

Time complexity

  • In general, the number of times the basic operation is repeated in the algorithm is a function of the problem scale n, which is expressed by T(n). If there is an auxiliary function f(n), so that when n approaches infinity, the limit value of T(n)/f(n) is a constant that is not equal to zero, then f(n) is a function of the same order of magnitude of T(n). It is recorded as T(n) = O (f(n)), which is called o (f(n)) Is the progressive time complexity of the algorithm, referred to as time complexity.

Worst time complexity

  • In the worst case, the time complexity is the upper bound of the running time of the algorithm on any input instance, which ensures that the running time of the algorithm will not be longer than any other instance.

Average time complexity

  • The average time complexity refers to the expected running time of the algorithm when all possible input instances occur with equal probability. Let the probability of occurrence of each case be PI, and the average time complexity be sum(pi*f(n))
    And average time complexity

Spatial complexity

  • The spatial complexity of a program refers to the amount of memory required to run a program.

be careful

  • The comparison based sorting algorithm has the fastest time complexity of O(nlogn)
  • In some cases, O(n ²) It will also be faster than O(nlogn) (the data length is small). Generally, when used in the algorithm, the amount of data can exceed the critical point, so we generally pay attention to the complexity level of the algorithm
  • Nonlinear comparison algorithm, cardinality sorting and counting sorting are special bucket sorting. Bucket sorting is a space for time algorithm

Algorithm comparison table

1, Bubble sorting

Algorithm idea:

  • Compare the adjacent elements in pairs, and exchange if the order is opposite. In this way, each trip will "float" the smallest or largest element to the top, and finally achieve complete order.
function bubbleSort(arr){ 
  for(let i=0;i<arr.length;i++){
    for(let j=1;j<arr.length-i;j++){
      if(arr[j-1] > arr[j]){
        let swap = arr[j-1]
        arr[j-1] = arr[j]
        arr[j] = swap
      }
    }
  } 
}

2, Select sort

Algorithm idea:

  • First, find the smallest (large) element in the unordered sequence and store it at the beginning of the sorted sequence. Then, continue to find the smallest (large) element from the remaining unordered elements, and then put it at the end of the sorted sequence. And so on until all elements are sorted.
function selectSort(arr){
  for(let i=0;i<arr.length;i++){
    let min = i
    for(let j=i+1;j<arr.length;j++){
      if(arr[min] > arr[j]){
        min = j
      }
    }
    if(i != min){
      let swap = arr[i]
      arr[i] = arr[min]
      arr[min] = swap 
    }
  }
}

3, Insert sort

Algorithm idea:

  • In each step, a record to be sorted is inserted into the ordered sequence that has been arranged before until all elements are inserted.
function insertSort(arr){
  for(let i=1;i<arr.length;i++){
    let cur = i
    while(arr[cur] < arr[cur-1]){
      let swap = arr[cur]
      arr[cur] = arr[cur-1]
      arr[cur-1] = swap
      cur--
    }
  } 
}

4, Quick sort

Algorithm idea:

  • Through one-time sorting, the data to be sorted is divided into two independent parts. All data in one part is smaller than all data in the other part, and then the two parts of data are sorted quickly according to this method. The whole sorting process can be recursive, so that the whole data becomes an ordered sequence.
function quickSort(arr){
  if(arr.length <2){
    return arr
  }
  let left = []
  let right = []
  let mid = arr.splice(0,1)[0]
  for(let i=0;i<arr.length;i++){
    if(arr[i] > mid){
      right.push(arr[i])
    }else{
      left.push(arr[i])
    }
  }
  return quickSort(left).concat(mid, quickSort(right))
}

5, Heap sort

Algorithm idea:

  • The characteristic of heap is that the element at the top of the heap is a maximum value, the top of the large top heap is the maximum value, and the small top heap is the minimum value.
  • Heap sorting is to exchange the elements at the top of the heap with the last element. After exchange, the characteristics of the heap are destroyed. We then form a large top heap again with the remaining elements in the heap, and then exchange the elements at the top of the heap with the last second element... This goes on and on. When there is only one remaining element, the array is ordered at this time.
function swap(arr, i, j){
  let swap = arr[i]
  arr[i] = arr[j]
  arr[j] = swap
}
function sort(arr){
  for(let i=Math.floor(arr.length/2)-1;i>=0;i--){
    heap(arr, i, arr.length)   
  }
  for(let i=arr.length-1;i>0;i--){
    swap(arr, 0, i)
    heap(arr, 0, i)
  }
}
function heap(arr, i, length){
  let temp = arr[i]  
  for(let k=2*i+1;k<length;k=2*k+1){
    if(k+1 < length && arr[k] < arr[k+1]){
      k++
    }
    if(temp < arr[k]){
      arr[i] = arr[k]
      i = k
    }else{
      break;
    }
    arr[i] = temp
  }
}

6, Merge sort

Algorithm idea:

  • To order a large unordered array, we can divide the large array into two, then sort the two arrays respectively, and then merge the two arrays into an ordered array. Because the two small arrays are ordered, the merging is very fast.
  • Divide the large array recursively until the size of the array is 1. At this time, there is only one element, so the array is ordered. Then merge the two arrays with the size of 1 into one with the size of 2, and then merge the two arrays with the size of 2 into four... Until all small arrays are merged.
function merge(begin,end){
  if(end-begin <2){
    return
  }
  let mid = begin + end >> 1
  merge(begin,mid)
  merge(mid,end)
  sort(begin,mid,end)
}
function sort(begin, mid, end){
  let li = 0,le = mid-begin
  let ri = mid,re = end
  let ai = begin
  let leftArray = []
  for(let i=0;i<le;i++){
    leftArray[i] = arr[begin++]
  }
  while(li < le){
    if(ri < re && arr[ri] <= leftArray[li]){
      arr[ai++] = arr[ri++]
    }else{
      arr[ai++] = leftArray[li++]
    }
  }
}

7, Hill sort (reduce incremental sort)

Algorithm idea:

  • Hill sorting is to group records according to a certain increment of subscript, and use the direct insertion sorting algorithm for each group; as the increment gradually decreases, each group contains more and more keywords. When the increment decreases to 1, the whole file is divided into one group, and the algorithm terminates.
function shell(arr){
  let step = stepArr(arr)
  for(let i=0;i<step.length;i++){
    insert(arr,step[i])
  }
}
function stepArr(arr){
  let step = arr.length
  let squense = []
  while((step>>=1)>0){
    squense.push(step)
  }
  return squense
}
function swap(arr,i,j){
  let swap = arr[i]
  arr[i] = arr[j]
  arr[j] = swap
}
function insert(arr, step){
  for(let col = 0;col < step;col++){
    for(let i=col+step;i<arr.length;i+=step){
      let cur = i
      while(cur > 0 && arr[cur] < arr[cur-step]){
        swap(arr,cur,cur-step)
        cur-=step
      }
    }
  }
}

8, Count sort

Algorithm idea:

  • Take the array element as the subscript of the array, and then count the number of occurrences of the element with a temporary array. For example, temp[i] = m, indicating that element I has occurred m times in total. Finally, summarize the data of the temporary array from small to large. At this time, the summarized data is orderly.
function countSort(arr){
  let max = arr[0]
  for(let i=1;i<arr.length;i++){
    if(arr[i] > max){
      max = arr[i]
    }
  }
  let count = []
  count.length = max+1
  count.fill(0,0,max+1)
  for(let i=0;i<arr.length;i++){     
    count[arr[i]]++
  }
  let newArray = []
  for(let i=0;i<count.length;i++){
    while(count[i] > 0){
      newArray.push(i)
      count[i]--
    }
  }
}

9, Cardinality sort

Algorithm idea:

  • First sort the data by the size of single digits, then sort the majority by the size of ten digits, then sort by the size of hundreds, and so on... Finally, there is a group of ordered elements.
function baseSort(arr){
  let max = arr[0]
  for(let i=1;i<arr.length;i++){
    if(max < arr[i]){
      max = arr[i]
    }
  } 
  let j=0
  while(Math.pow(10,j) <= max){
    let array = []
    array.length = 10
    for(let i=0;i<10;i++){
      array[i] = new Array()
    }
    for(let i=0;i<arr.length;i++){
      let digit = Math.floor(arr[i] / Math.pow(10,j)) % 10
      let len = array[digit].length 
      array[digit][len] = arr[i]
    }
    arr = []
    for(let i=0;i<array.length;i++){
      if(array[i].length>0){
        arr = arr.concat(array[i])
      }
    }
    j++
  }
}

10, Bucket sorting

Algorithm idea:

  • Cardinality sorting and counting sorting are special bucket sorting. The main idea is to put an array of length n into k buckets according to certain rules, sort and merge them respectively.
    Time complexity:
    (n/k)lg(n/k)k+n => n(lgn-lgk)+n => n+k

Posted by romano2717 on Wed, 27 Oct 2021 18:45:26 -0700