22计算机408考研—数据结构—快速排序

96 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情

2022计算机考研408—数据结构—排序 手把手教学考研大纲范围内的排序 22考研大纲数据结构要求的是C/C++,笔者以前使用的都是Java,对于C++还很欠缺, 如有什么建议或者不足欢迎大佬评论区或者私信指出

Talk is cheap. Show me the code. 理论到处都有,代码加例题自己练习才能真的学会

快速排序

思路: 从未排序的数组中,一个一个的寻找,寻找当前值应该在排序后数组的位置, 以此类推,把每个值的位置都确定了以后,此数组就变成了排序后的数组 也是分段进行确定某个值最终排序后的下标

先选取第一个值,用一个临时变量保存这个值,然后双指针i表示这段范围的开头,j这段范围的结尾    
	j负责从后向前找小于临时变量的值,找到以后就把j的值放到i那,
		此时j位置就空出来了,我们当作把临时变量的值放到j这里
	i负责从前向后找大于临时变量的值,找到后就放到j那里,
		此时i位置就空出来了,我们同样当作把临时变量的值放到i这里
	不断循环这两步的操作,
	i是从前向后,j是从后向前
	循环结束的条件就是i==j  也就是临时变量排序后数组的位置,
	按照这种排序方式,结束后,
		比临时变量小的都在临时变量左边(左边不一定是排好序的),
		比临时变量大的都在临时变量右边(右边不一定是排好序的),
		也就是说临时变量当前的下标就是排序后的下标			
	
当前临时变量的位置确定好以后,我们可以分为前半部分和后半部分继续这种操作
以此类推,当每个值最终排序后的位置都确定的时候,此数组为排序后的数组		

下图为确定好一个值的最终位置的排序图

临时变量为50,左指针low,右指针high 在这里插入图片描述 右指针找到20比临时变量小,交换两个值 在这里插入图片描述 左指针找到90比临时变量大,交换两个值 在这里插入图片描述 右指针找到40比临时变量小,交换两个值位置 在这里插入图片描述 左指针找到70比临时变量小,交换两个值的位置 在这里插入图片描述 右指针左移与左指针重合,当前位置为50排序后的最终位置 在这里插入图片描述 我们发现,左边的数都比50小,右边的数都比50大, 当前数的位置就是排序后当前数的位置 然后在把左边的数组按照这种方法,右边的数组按照这种方法 以此类推每个值的最终下标都确定下来了,数组为排序后的数组 PS:图仍然是某度当来的o( ̄▽ ̄)ブ

#include <iostream>
#include <vector>

using namespace std;


void quickSort(vector<int> &num, int left, int right);

int main() {
    int n;    //n为将要输入的数组长度
    cin >> n;   //输入n   cin方法需要上面使用std
    vector<int> num;    //定义vector  记得上面导入vector
    int temp;   //temp为输入vector时的中间变量
    for (int i = 0; i < n; i++) {
        cin >> temp;            //输入
        num.push_back(temp);
    }
    quickSort(num, 0, num.size() - 1);    //调用自定义的排序方法
    cout << "\n\n排序后" << "\n";
    for (int i = 0; i < num.size(); i++) {
        cout << num[i] << " ";     //输出
    }
    return 0;
}

void quickSort(vector<int> &num, int left, int right) {
    if (left >= right) return;      //如果左节点>=右节点了,证明排序结束了,返回即可
    int temp = num[left];   //保存一下当前左节点的值,此次排序就是确定当前左节点的值
    int l = left;   //保存一下原始的左右边界
    int r = right;
    while (left < right) {      //循环的结束条件就是左指针 == 右指针,相等时就为temp排序后的最终位置
        while (left < right && temp < num[right]) { //右指针找比temp小的值,如果没找到就一直找
            right--;
        }
        if (left < right) {         //上面循环结束了就证明找到了,如果left == right,那么最终位置就确定好了,
            num[left] = num[right]; //然后把比temp小的放到左面left位置那里,然后left指向下一个值
            left++;                 //可能这里有些疑问,上面描述的是交换,这里没有交换,实际上每次都交换,换来换去,每次都重复换temp这个数
        }                           //不如直接赋值,然后把这个重复数直接放到最后确定的位置

        while (left < right && num[left] < temp) {  //这里是左指针找比temp大的数,找到就退出循环了,
            left++;
        }
        if (left < right) {     //与上面相反的道理,把比temp大的数放到right,right指针左移
            num[right] = num[left];
            right--;
        }
    }
    num[left] = temp;   //循环结束就是确定了temp最终的位置,左指针==右指针

    //每次循环都把数组的变动输出出来
    cout << "\n左边界下标:" << l << " 右边界下标:" << r << " 当前循环确定的下标为:" << left << "\n";
    for (int j = 0; j < num.size(); j++) {
        cout << num[j] << " ";
    }

    quickSort(num, l, left - 1);    //temp确定好了位置,把temp左面的数组和右面的数组分别进行这种方法排序
    quickSort(num, left + 1, r);    //当每个值的下标都确定的时候,该数组以完成排序
}

在这里插入图片描述