其实也没什么,就是每次挑出一个数(通常选相对第一个数),作为中间的“裁判”,划分左右部分的过程。
具体的细节可能需要注意。
比如元素的序号是从1~N的,存放在A[]中。 我们首先把A[1]元素值提取出,存放在临时变量temp
中,这样,
所以利用two pointers 思想,left指针指向A[1]位置,right指针指向A[N],然后我们注意,先动的,是right指针。
只能向左移动了,但是动之前需要先判断**

首先判断A[N]是否小于等于temp变量,如果满足条件,就把A[N]元素与A[1]元素交换,还是注意,
****A[1]元素的值是无关紧要的因为我们早已经用temp变量保存了下来。但是交换之后,也就意味着A[N]元素的值变成无关紧要的,
我们不能对A[1]随便修改了
因为此时保存 原来A[N]元素的关键人物,只有A[1]了,如果我们再对它一不小心进行了别样的修改,也就是讲一个没有额外备份的元素销毁,它将灰飞烟灭。**
所以接下来该怎么办呢?继续移动指针并进行判断。
那么移动left还是right呢?判断什么呢?
并将其原来的位置作为下一个可以继续我们“蹂躏”的位置。
而A[N]的位置显然是在最右边的。移动什么呢?
只能是移动left指针了。
将left指针向右移动,直到出现A[i]元素大于temp的时候,就将A[i]元素与A[N]元素互换,此时,无关紧要的位置又变成了A[i],就这样循环下去。直到left指针和right指针相遇。
也就是
所以这只是一次,以A[1]作为裁判划分出了“大致有序”的左半部分和右半部分。我们还需要分别对左右两边继续实行同样的策略。

我这里所谓的“大致有序”,就是以“裁判”为准,左边部分都是小于裁判的元素,右边部分都是大于裁判的元素,但是左边部分不保证有序,右边部分也不保证有序。
这也是还需要对左边部分和右边部分分别进行同样的以上操作的必要原因。

总结一下,关键点:
1.two pointers;
2.分治,递归;
3.其实我觉得很关键的,反倒是一个临时变量temp,保存“裁判”元素,也就是意味着,
原来的数组A[]多出了一个“无关紧要”的,我们可以任意移动的元素位置,利用这一点,就好像踢皮球一样,左一脚右一脚。
直到裁判元素的位置最终确定。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cstring>
#include <sstream>
#include <cmath>
#include <vector>
#include <algorithm>


using namespace std;


int quick(int a[],int left,int right)
{
    int temp=a[left];

    while(left<right)
    {
        while(left<right && a[right]>temp )
        {
            right--;
        }

        a[left]=a[right];

        while(left<right &&  a[left]<=temp )
        {

            left++;
        }

        a[right]=a[left];

    }



    a[left]=temp;

    return left;





}





void quick_sort(int a[],int left,int right)
{

    if(left<right)
    {
        int mid=quick(a,left,right);

        quick_sort(a,left,mid-1);
        quick_sort(a,mid+1,right);



    }





}





int main()
{


    int a[]={
  1,4,4,5,3,2,8,7,9};

    for(int i=0;i<9;i++)
    {
        cout<<a[i]<<" ";

    }

    cout<<endl;


    quick_sort(a,0,8);

    for(int i=0;i<9;i++)
    {
        cout<<a[i]<<" ";

    }

    cout<<endl;




    return 0;
}