[data structure and algorithm] - * quick sort*

Today, Xiaoxuan brings you a sort method commonly used in code - quick sort

Algorithm Introduction

Quick Sort evolved from bubble sort, which is actually bubble sort   Recursive divide and conquer.

Quick sort selects a benchmark element in each round, and moves other larger elements to one side of the sequence and smaller elements to the other side of the sequence, so as to disassemble the sequence into two parts.

The specific process is as follows:

  1. Split the local array of objects into two local arrays (Divide)
  2. Perform quickSort(Solve) on the first half of the array
  3. Perform quickSort(Solve) on the second half of the array

Algorithm analysis  

Our implementation needs to determine the dividing point x - Take q [(l + r) / 2] or     Random value

Then use the double pointer to operate - L R  

We ensure that the number to the left of the demarcation point is less than or equal to x

The numbers on the right of the dividing point are greater than x

L++ R --, until l finds the number > x and R finds the number less than or equal to x, exchange the two numbers

  This process continues until the two pointers meet   —— L >=   R

Next, we just need to continue the process recursively.

Code ideas

1, "Violence handling"

  1. Create two arrays a[] b []
  2. Create storage array q[]  
    1.   q[l ~ r] (if q[i]   <= x   ——  x -> a[])   
    2.   q[l ~ r]   (if q[i]   > x   ——  x -> b[])
  3. Result input
    1. ​​​​​​​a[]  -> q[]         
    2. b[]  -> q[]

 

2, Graceful solution (operate in the original array according to the above ideas)

 

The general idea is shown in the figure above.

code implementation  

C language

#include <stdio.h>

int arr[1000],n;   //Define global variables that need to be used in functions

void quicksort(int left,int right)
{
    int i = 0;
    int j = 0;
    int t = 0;
    int temp = 0;
    
    if(left > right)
        return;
    
    temp = arr[left];  //The benchmark number is stored in temp
    i = left;
    j = right;
    while(i != j)
    {
        //Order is very important. Look from right to left
        while(arr[j] >= temp && i < j)
            j--;
        while(arr[i] <= temp && i < j)
            i++;
        
        //Swap the positions of two numbers in the array
        if(i < j) //When sentry i and sentry j did not meet
        {
            t = arr[i];
            arr[i] = arr[j];
            arr[j] = t;
        }
    }
        
        //Finally, return the reference number
        arr[left] = arr[i];
        arr[i] = temp;
        
        quicksort(left,i-1);
        quicksort(i+1,right);
        return;
}

int main()
{
    int i = 0;
    int j = 0;
    scanf("%d",&n);
    for(i = 0;i < n ;i++)
    {
        scanf("%d",&arr[i]);
    }
   
    quicksort(0,n-1);
    
    for(i = 0;i < n - 1;i++)
        printf("%d ",arr[i]);
     printf("%d",arr[n - 1]);
    return 0;
}

c++

#include <iostream>

using namespace std;

const int N = 1e6 + 10;

int n;
int q[N];

void quick_sort(int q[],int l,int r)
{
    if(l >= r) return;
    
    int i = l - 1,j = r + 1, x = q[(l + r) >> 1];
    while(i < j)
    {
        do i ++; while(q[i] < x);
        do j --; while(q[j] > x);
        if(i < j) swap(q[i],q[j]);
    }
    
    quick_sort(q, l, j);
    quick_sort(q, j + 1, r);
}

int main()
{
    scanf("%d",&n);
    for(int i = 0;i < n;i++) scanf("%d",&q[i]);
    
    quick_sort(q,0,n - 1);
    
    for(int i = 0;i < n;i++) printf("%d ",q[i]);
    
    return 0;
}

Extended discussion

  Quick sort is based on divide and conquer like merge sort.   However, the sorting has been completed in the original array when the partition is executed, so there is no need to merge manually as in merge sorting.

Quick sort will exchange non adjacent elements in the process of segmentation, so it is an unstable algorithm. On the other hand, merge sort requires O (n) external storage space, and quick sort does not need additional memory. In other words, quick sort is an in-situ algorithm (internal sort).

If the intermediate value can be exactly obtained during segmentation, the whole process is roughly divided into log2n layers like merging sorting. The time complexity of quick sorting is O (logn), which is the most efficient sorting algorithm in general. However, if we choose a fixed way to select the benchmark, the efficiency will be greatly reduced when processing some data (such as the sorted data), and even reach O(n2) in the most complex case. Moreover, some sequential data may make the recursion depth too deep and eventually lead to stack overflow. In general, we need to pay more attention to the way of selecting the benchmark, such as random selection, or taking the intermediate value after selecting several.

This is the end of today's article. If you think it is helpful to you, please give Xiaoxuan:

 

 

 

Tags: C Algorithm data structure

Posted on Mon, 22 Nov 2021 22:31:04 -0500 by div