Sort - quick sort (fast and slow pointer Implementation)

Posted by dnoonan on Sun, 27 Feb 2022 05:13:03 +0100

The two solutions of too fast scheduling summarized before can be used as a reference Two common solutions of fast scheduling Recently, I found another method that is easier to understand. Make a record here.

This is a method of using "fast and slow pointer comparison" to realize the fast sorting algorithm.

The key to realize the quick sorting algorithm is to select a number in the array (which can be understood as the axis value), and divide the number in the array into two parts. The number smaller than the selected number is moved to the left of the array, and the number larger than the selected number is moved to the right of the array.

int partition(vector<int>& nums, int start, int end) {

    int index = (start + end) / 2;
    swap(nums, index, end);

    int small = start - 1;
    for (index = start; index < end; ++index) {
        if (nums[index] < nums[end]) {
            ++small;
            if (small != index) {
                swap(nums, small, index);
            }

        }
    }

    ++small;
    swap(nums, small, end);
    return small;
}

Explanation:

Here, index is the fast pointer and small is the slow pointer,

The elements of the position pointed by the slow pointer are larger than the axis value. When the fast pointer is compared with the axis value and the corresponding value is smaller than the axis value, the values of the fast pointer and the slow pointer are exchanged, that is, the small ones are put in front. When the fast and slow pointers are the same, there is no need to exchange,

Because after the last exchange, small points to the result of the last exchange, which is smaller than the axis value. Move the slow pointer small back one. In this exchange, move the new small element pointed by the fast pointer index to the front. If small is equal to index, there is no need to exchange. If small is not equal to index, the element between small and index must be larger than the axis value, so it can be realized, Put the small elements in the front and the large elements in the back. If you don't know what you hear here, I suggest you draw your own picture and actually walk through it.

Ensure that the slow pointer starts from - 1 and then adds back, and the value on it and the axis value are finally exchanged to complete a round of partition.

Edge condition

If the corresponding value of the first random index is the maximum number, the partition only adjusts the maximum number to the last,

If the corresponding value of the first random index is the smallest number, a round of partition only adjusts the smallest number to the top.

Complete example

Examples: 65,58,95,10,57,62,13106,78,23,85

#include<vector>
#include<iostream>
#include<cstdlib>
using namespace std;

void swap(vector<int>& nums, int one, int two) {    // Exchange operation
    int temp = nums[one];
    nums[one] = nums[two];
    nums[two] = temp;
}

int partition(vector<int>& nums, int start, int end) {    // One round array segmentation
    int index = (start + end) / 2;    // The most scientific method is to randomly select the axis value, and it is also possible to select the median value here
    swap(nums, index, end);            // Put the axis value at the end of the array. After a round of partition comparison, exchange the axis value back to the position where the axis value should be after sorting

    int small = start - 1;        // Ensure that the slow pointer small starts from 0
    for (index = start; index < end; ++index) {        // Only the numbers between start and end-1 are exchanged and compared
        if (nums[index] < nums[end]) {        // When the condition that the value of the fast pointer is less than the axis value is met
            ++small;                        // Because after the last exchange, small points to the result of the last exchange, which is smaller than the axis value. Move the slow pointer small back one. In this exchange, move the new small element pointed by the fast pointer index to the front. If small is equal to index, there is no need to exchange. If small is not equal to index, the element between small and index must be larger than the axis value, so it can be realized, Put the small elements in the front and the large elements in the back. If you don't know what you hear here, I suggest you draw your own picture and actually walk through it.
            if (small != index) {            // When the speed pointer is the same, there is no need to exchange
                swap(nums, small, index);
            }

        }
    }

    ++small;        // Since 1 was subtracted at the beginning of initialization, the position of the last axis value to be initialized should be small plus 1
    swap(nums, small, end); // Change the axis value to the correct position after a division. The front of the axis value is all smaller than it, and the back of the axis value is all larger than it
    return small;
}

void quicksort(vector<int>& nums, int start, int end) {
    if (start == end)    // Exit when equal and merge from bottom to top
        return;
    int index = partition(nums, start, end);    // division
    if (index > start) {            // Edge condition restrictions must be added, otherwise it will lead to access to addresses outside the array and overflow
        quicksort(nums, start, index - 1);
    }
    if (index < end) {                // ditto
        quicksort(nums, index + 1, end);
    }
}

int main() {
    vector<int> numbers{3,2,1,5,6,4};

    quicksort(numbers, 0, numbers.size() - 1);

    for (int i = 0; i < numbers.size(); i++) {
        cout << numbers[i] << endl;
    }
    system("pause");
    return 0;
}

Topics: C++ Algorithm