算法入门--快速排序

 参考思路快速排序算法_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1at411T75o/?spm_id_from=333.1007.top_right_bar_window_history.content.click&vd_source=e4463ee0b281106a9dc0dec11813ce26感觉他解释得比较清晰,根据这个思路写,多写几遍应该就能记住,做个备份。

import <iostream>;
import <random>;
import <functional>;

void quickSort(int array[], int left, int right) 
{
    int pivot = array[left]; // 标杆值/基准值
    int l_pointer = left+1, r_pointer = right;   //l_pointer向右移动一位
    //std::cout << "Pivot: " << pivot << std::endl;
    // 将数组分为两部分;对于下面的while循环,一个循环做了两件事:针对左右两个指针,要么移动,要么交换值
    // 针对每一次while循环,分三种情况:
    //1、如果右指针移动了,说明右指针的值本来就大于或等于pivot;下一个if,如果左指针移动了,说明左指针的值本来就小于或等于pivot;这种情况可能会导致循环最后左指针比右指针大1,应当在循环结束后做检查
    //2、如果右指针移动了,说明右指针的值本来就大于或等于pivot;下一个if,如果左指针和右指针值交换了,即让左指针的比pivot大的值去了右指针那,那么下一次while循环右指针一定会向左移动一位(避免重复检查和死循环);
    //3、如果右指针和左指针交换了,即让右指针的比pivot小的值去了左指针那,那么这次循环的下一个if左指针一定会向右移动一位(避免重复检查和死循环)
    while (l_pointer < r_pointer)   //当左右指针重合时停止移动
    {
        if (array[r_pointer] >= pivot)  //先移动右指针,当右指针上的值大于或等于pivot时,将右指针向左移动一位
            r_pointer--;
        else                            //当右指针的值小于pivot时,让右指针的值与左指针的值交换
            std::swap(array[l_pointer], array[r_pointer]);
        if (array[l_pointer] <= pivot )  //再移动左指针,当左指针上的值小于或等于pivot时,将左指针向右移动一位
            l_pointer++;
        else                            //当左指针的值大于pivot时,让左指针的值与右指针的值交换
            std::swap(array[l_pointer], array[r_pointer]);
    }
    //一定要分析最终l_pointer和r_pointer相邻时的四种情况:  !!!!
    //假设pivot=6,当l-pointer和r_pointer相邻时,有四种情况需要考虑;
    //1、l_pointer的值是5,r_pointer的值是7;->最终l_pointer=r_pointer+1
    //2、l_pointer的值是7,r_pointer的值是5;->最终l_pointer=r_pointer
    //3、l_pointer的值是5,r_pointer的值是5;->最终l_pointer=r_pointer
    //4、l_pointer的值是7,r_pointer的值是7;->最终l_pointer=r_pointer+1
    if (r_pointer == l_pointer-1)   //针对l_pointer=r_pointer+1,把pivot值放到r_pointer的位置
        std::swap(array[--l_pointer], array[left]);  //同时将l_pointer移动至r_pointer处
    else                            //针对l_pointer=r_pointer,有两种情况:两个指针的值是小于或等于pivot,还是大于pivot
    {
        if (array[l_pointer] <= pivot)    //如果指针的值小于或等于pivot,就直接交换指针与pivot的值(因为此时指针位置前面的值都会小于pivot)
            std::swap(array[l_pointer], array[left]);
        else                              //如果指针的值大于pivot,就需要交换指针前一位与pivot的值(不然会把这个大于pivot的值放到left的位置)
        {
            std::swap(array[l_pointer - 1], array[left]);
            l_pointer--;                  //把l_pointer和r_pointer移到交换点
            r_pointer--;
        }
    }
    //std::cout << "l_pointer and r_pointer: " << l_pointer << " " << r_pointer << std::endl; 
    //经过上面的双指针的移动,结果应该是l_pointer和r_pointer位置重合,这个位置左边的数小于或等于pivot,这个位置右边的数大于或等于pivot
    //可以先把下面的递归函数注释掉,先试试上面的l_pointer和r_pointer是不是相等,以及对应的值是否等于pivot。
    //下面是递归函数,递归的基线条件是pivot左右两边的数组大小为1
    if (l_pointer > left+1 ) quickSort(array,left,l_pointer-1);   //只有当pivot左边的数组大小大于1时才需要进一步排序
    if (r_pointer < right-1) quickSort(array,r_pointer+1,right);  //只有当pivot右边的数组大小大于1时才需要进一步排序
}

auto createUniformPseusoRandomNumber(int max)
{
    std::random_device seeder;
    std::default_random_engine generator{ seeder() };
    std::uniform_int_distribution distribution{ -10,max };
    return std::bind(distribution, generator);
}

int main()
{
    //int numbers[]{ 3,-3,6,7,3,2,2,1,3,5,1 };
    //std::cout << "Size: " << std::size(numbers) << std::endl;
    //quickSort(numbers,0,std::size(numbers)-1);
    //for (size_t i{ 0 }; i < std::size(numbers); ++i)
    //    std::cout << i << "\t" << numbers[i] << std::endl;
    auto random{ createUniformPseusoRandomNumber(20) };
    int numbers[]{ random(),random(),random(),random(),random(),random(),random(),random(),random(),random()};
    for (size_t i{ 0 }; i < std::size(numbers); ++i)
        std::cout << numbers[i] << "\t";
    std::cout << std::endl;
    std::cout << "Size: " << std::size(numbers) << std::endl;
    quickSort(numbers,0,std::size(numbers)-1);
    for (size_t i{ 0 }; i < std::size(numbers); ++i)
        std::cout << i << "\t" << numbers[i] << std::endl;
    return 0;
}

因为要测试quickSort,总是手动改数组有点麻烦,再写了一个createUniformPseusoRandomNumber函数用来生成整数随机数。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值