C++快排的三种方式

news/2024/5/19 21:29:06 标签: 快速排序, c++

文章目录

  • 前言
  • 引例:三色旗问题
  • 快速排序
    • 方式一:三个下标
    • 方法二:一般解法
    • 方式三:挖坑法
  • 总结


前言

最近学习了快速排序,简单记录一下。


引例:三色旗问题

问题描述:
有一个只由0,1,2三种元素构成的整数数组,请使用交换、原地排序而不是使用计数进行排序。

解题思路:
定义两个下标left和right;
left的含义:使数组中<=left的部分都比1小,left的初始值为-1;
right的含义:使数组中>=right的部分都比1大,right的初始值为n;
从index = 0开始遍历;
根据index所指向的值分别进行不同的操作;
如果a[index] = 0,与left对应的值交换;
如果a[index] = 1,index++;
如果a[index] = 2,与right对应的值交换。

代码如下:

void holand(int a[], int n) {
    int index = 0, left = -1, right = n;
    while (index < right) {
        if(a[index] == 0) {
            swap(a[index++], a[++left]);
        }
        else if (a[index] == 1) {
            index++;
        }
        else if (a[index] == 2) {
            swap(a[index], a[--right]);
        }
    }

}

快速排序

方式一:三个下标

这个快排的思想和三色旗问题的思想差不多。选择一个基准值,创建两个下标(加上基准值的下标就是三个了),使得小于前一个下标的位置全都比基准值小,大于后一个下标的位置的值都比基准值大。

这个方法是遍历到大于或者小于基准值就马上交换基准值和遍历到的元素的位置。

代码如下:

void quickSort(vector<int>& nums, int left, int right) {
    if (left > right) return;
    int stand = nums[left], index = left, i = left - 1, j = right + 1;
    while (index < j) {
        if (nums[index] < stand) {
            swap(nums[index++], nums[++i]);
        }
        else if (nums[index] > stand) {
            swap(nums[index], nums[--j]);
        }
        else
        {
            index++;
        }
    }
    nums[--index] = stand;  //之前的 if(nums[index] < stand)中的语句会多加一个1,此处将它减去
    quickSort(nums, left, index - 1);
    quickSort(nums, index + 1, right);
}

方法二:一般解法

  1. 先找大于基准值的元素,
  2. 再找小于基准值的元素,
  3. 然后交换两个元素,
  4. 遍历直到两个下标相遇,
  5. 最后后把基准值放在两个下标相遇的位置。

注意:这里先找大于基准值的元素,后找小于基准值的元素,这个顺序不能改变。这和最后将基准值放到指定位置时有关。

void quickSort2(vector<int>& nums, int left, int right) { //找一大一小数,然后交换
    if (left >= right) return;
    int i = left, j = right, temp = nums[left];
    while (i != j) {
        while (i < j && nums[j] >= temp) {
            j--;
        }
        while (i < j && nums[i] <= temp)
        {
            i++;
        }
        Swap(nums[i], nums[j]);
    }
    nums[left] = nums[i];
    nums[i] = temp;
    quickSort2(nums, left, i);
    quickSort2(nums, i + 1, right);

方式三:挖坑法

  1. 将基准值的位置作为坑(一般是第一个)。
  2. 先移动左下标,找比基准值小的元素,将这个元素填到坑的位置,此时坑的位置就是刚刚找到的元素的位置
  3. 再移动右下标,找比基准值大的元素,将这个元素填到刚刚的坑的位置。
  4. 直到两个下标相遇。
  5. 将基准值填到两个下标相遇的位置。
void quickSort3(vector<int>& nums, int left, int right) {
    if (left >= right) return;
    int i = left, j = right, temp = nums[left], index = left;
    while (i != j) {
        while (i < j && nums[j] >= temp) {
            j--;
        }
        nums[index] = nums[j];
        index = j;
        while (i < j && nums[i] <= temp)
        {
            i++;
        }
        nums[index] = nums[i];
        index = i;
    }
    nums[i] = temp;
    quickSort3(nums, left, i);
    quickSort3(nums, i + 1, right);
}

总结

总的来说还是挖坑法比较好,因为前两个方法每次都需要调用交换函数(swap),而挖坑法只用简单的赋值。同时我们可以发现第一种方法调用交换函数的频率比第二种方法要高很多。
笔者认为挖坑法的注意点是跟踪好坑的位置。坑的位置记好了,然后按照一大一小的顺序填坑就行了。


http://www.niftyadmin.cn/n/1569283.html

相关文章

leetcode:136.只出现一次的数字

文章目录题目hash表另外两种空间复杂度为O(n)的两种方法异或运算总结题目 给定一个非空整数数组&#xff0c;除了某个元素只出现一次以外&#xff0c;其余每个元素均出现两次。找出那个只出现了一次的元素。 说明&#xff1a;你的算法应该具有线性时间复杂度。 进阶&#xf…

C++ 单向链表

文章目录前言头文件cpp文件前言 最近终于闲下来了&#xff0c;把之前写的单向链表代码总结上传一下。 头文件 //声明头节点 struct Node {int val;Node* pNext;Node(int val) {this->val val;this->pNext NULL;} };//声明链表类 class List { public://创建链表Node*…

C++二叉搜素树的创建,前、中、后序遍历(递归和非递归),层次遍历

文章目录前言一、头文件&#xff08;节点类、树类以及遍历方法的声明&#xff09;二、cpp文件构建二叉搜素树递归遍历二叉树非递归遍历二叉树层次遍历遍历前言 总结一下树的代码。 一、头文件&#xff08;节点类、树类以及遍历方法的声明&#xff09; #pragma once #include …

交叉验证[转]

交叉验证&#xff08;Cross validation)&#xff0c;有时亦称循环估计&#xff0c; 是一种统计学上将数据样本切割成较小子集的实用方法。于是可以先在一个子集上做分析&#xff0c; 而其它子集则用来做后续对此分析的确认及验证。 一开始的子集被称为训练集。而其它的子集则被…

《这些道理没有人告诉过你》摘记

几个月前找实习的时候囫囵吞枣地看了一遍《这些道理没有人告诉过你》&#xff0c;觉得讲得还不错&#xff0c;现在重看&#xff0c;顺便写一下读书笔记。 1 择业主要从四个方面进行选择&#xff1a;行业&#xff0c;职业&#xff0c;公司&#xff0c;薪资&#xff0c;而不是某个…

[转载】我的数据挖掘之路 by wrchow

导读&#xff1a;作者wrchow是浙江大学计算机硕士&#xff0c;通过自己的努力终于拿到了心仪的offer&#xff08;搜狗Web数据挖掘助理研究员&#xff09;&#xff0c;实现了从事互联网数据挖掘的梦想。他对数据挖掘这个行业的兴趣&#xff0c;以及为了进入这个行业所做的准备和…

大数据时代有感

最近媒体网络&#xff0c;校园&#xff0c;书籍文献到处都充斥着“大数据”“云”“超级计算”&#xff0c;大数据时代在我们没有意识到的时候就静悄悄地走近了我们&#xff0c;谷歌&#xff0c;阿里巴巴&#xff0c;搜狗一系列的公司摩拳擦掌&#xff0c;准备在大数据时代大干…

验证集,测试集,训练集

这三个名词在机器学习领域的文章中极其常见&#xff0c;但很多人对他们的概念并不是特别清楚&#xff0c;尤其是后两个经常被人混用。Ripley, B.D&#xff08;1996&#xff09;在他的经典专著Pattern Recognition and Neural Networks中给出了这三个词的定义。 Training set: A…