网站策划书格式,网络推广优化,备案通过网站还是打不开,企业网站开发框架目录 几大排序汇总
1.冒泡排序
性能:
思路和代码:
2.插入排序
性能:
思路和代码:
3.归并排序
性能:
思路和代码:
4.希尔排序
性能:
思路和代码:
5.选择排序
性能:
思路和代码:
6.堆排序
性能:
思路和代码:
topK问题
7.快速排序
性能:
思路和代码: 几大排…目录 几大排序汇总
1.冒泡排序
性能:
思路和代码:
2.插入排序
性能:
思路和代码:
3.归并排序
性能:
思路和代码:
4.希尔排序
性能:
思路和代码:
5.选择排序
性能:
思路和代码:
6.堆排序
性能:
思路和代码:
topK问题
7.快速排序
性能:
思路和代码: 几大排序汇总
排序算法可以分为内部排序和外部排序内部排序是数据记录在内存中进行排序而外部排序是因排序的数据很大一次不能容纳全部的排序记录在排序过程中需要访问外存。常见的内部排序算法有插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。用一张图概括 1.冒泡排序
性能:
时间复杂度: O(N^2)空间复杂度: O(1)稳定性: 稳定原地排序
时间复杂度:
冒泡排序算法的时间复杂度为O(N^2)其中N是数组的大小。
外层循环需要执行N-1次表示需要进行N-1趟排序。内层循环在第i趟排序时需要比较的次数为nums.size()-1-i次。因此总的比较次数为
(N-1) (N-2) ... 2 1 (N-1) * N / 2 (N^2 - N) / 2
空间复杂度:
冒泡排序算法是一种原地排序算法它只需要使用常数级别的额外空间来存储临时变量例如循环中的索引、交换时的临时变量等。随着输入规模的增加所需的额外空间大小并不会改变因此空间复杂度为O(1)。
思路和代码:
有四个数, 排完序需要三趟, 第一趟需要比较三次, 第二趟需要比较二次, 第三趟需要比较一次
把第一个元素与第二个元素比较如果第一个比第二个大则交换他们的位置。接着继续比较第二个与第三个元素如果第二个比第三个大则交换他们的位置….我们对每一对相邻元素作同样的工作从开始第一对到结尾的最后一对这样一趟比较交换下来之后排在最右的元素就会是最大的数。除去最右的元素我们对剩余的元素做同样的工作如此重复下去直到排序完成
优化一下冒泡排序的算法
假如从开始的第一对到结尾的最后一对相邻的元素之间都没有发生交换的操作这意味着右边的元素总是大于等于左边的元素此时的数组已经是有序的了我们无需再对剩余的元素重复比较下去了。
#include iostream
#include vector
using namespace std;void bubblesort(vectorint nums)
{if (nums.size() 2) return;for (int i 0; i nums.size() - 1; i) // 一共需要 n-1 趟{bool flag false;// 随着趟数的增加, 比较的次数随之减小for (int j 0; j nums.size() - 1 - i; j) // 第 i1 趟时, 一共需要比较多少次 { // 第 i1 趟时, 需要比较 nums.size()-1-i 次 if (nums[j] nums[j 1]){flag true;myswap(nums, j, j 1);}}if (flag false) // 一趟下来没有发生位置交换, 说明这是有序的集合, 因此直接break即可{break;}}
}
2.插入排序
性能:
时间复杂度: 最坏情况, 逆序O(N^2), 最好情况下O(N)空间复杂度: O(1)稳定的排序什么时候用插排高效? 小规模数据或者基本有序时越高效(移动少)
时间复杂度:
插入排序的时间复杂度取决于待排序数组的初始状态。在最坏情况下即待排序数组为逆序排列时插入排序的时间复杂度为O(N^2)其中N是数组的大小。
外部的for循环需要执行N-1次表示需要对N-1个元素进行插入操作。对于每个待插入的元素内部的while循环最多需要比较和移动该元素前面的所有元素最坏情况下为N-1次。因此总的比较和移动操作次数为1 2 3 ... (N-1) (N-1) * N / 2 (N^2 - N) / 2
需要注意的是在最好情况下即待排序数组已经是有序的情况下插入排序的时间复杂度为O(N)因为每个元素只需要与其前面的一个元素进行比较即可。
综上所述插入排序的时间复杂度在最坏情况下为O(N^2)在最好情况下为O(N)空间复杂度为O(1)。
空间复杂度:
插入排序的空间复杂度为O(1)即不需要额外的空间与输入规模相关。在插入排序算法中排序操作是通过原地交换和移动数组元素来实现的不需要使用额外的数组或数据结构存储临时结果。
无论输入数组的规模大小插入排序只需要常数级别的额外空间来存储一些辅助变量如循环变量、待插入元素的副本等。这些额外空间的使用与输入规模无关因此插入排序的空间复杂度是O(1)。
这是插入排序算法的一个优点尤其适用于空间有限的环境或对空间复杂度有要求的场景。
思路和代码:
这段代码实现了插入排序算法。插入排序的思路是将数组分为已排序和未排序两部分。初始时将第一个元素视为已排序部分从第二个元素开始逐个将未排序部分的元素插入到已排序部分的正确位置直到所有元素都被插入到已排序部分。
从数组的第二个元素开始遍历将当前元素视为待插入的元素。
将待插入元素与已排序部分的元素从后往前进行比较如果已排序部分的元素大于待插入元素则将该元素后移一位直到找到小于等于待插入元素的位置。
将待插入元素插入到找到的位置后面保持已排序部分的有序性。
重复步骤2和步骤3直到遍历完所有的待插入元素。
通过不断将待插入元素插入到已排序部分的正确位置最终实现了整个数组的排序。
#include iostream
#include vector
using namespace std;void insertsort(vectorint nums)
{// 第一个元素认为是有序的, 所以从第二个元素开始遍历for (int i 1; i nums.size(); i){int inserted nums[i]; // 待插入的元素int j i - 1;// 插入排序是稳定的排序算法当遇到相等的元素时应该停止向后移动以保持相对顺序不变。for (; j 0 nums[j] inserted; j--){nums[j 1] nums[j]; // 将比 inserted 大的元素向后移}nums[j 1] inserted; // 将 inserted 插入到正确位置}
}
/* 插入排序 */
void insertsort(vectorint nums)
{if(nums.size() 2) return;for(int i 1; i nums.size(); i){int inserted nums[i];int j i - 1;for(; j 0; j--){if(nums[j] inserted) {nums[j 1] nums[j];}else{break;}}nums[j 1] inserted;}
}
3.归并排序
性能:
时间复杂度: O(N*logN), 不管数据是有序的还是无序的, 都是这个时间复杂度空间复杂度: O(N)归并排序是稳定的非原地排序
时间复杂度:
归并排序的时间复杂度是O(nlogn)其中n是待排序数组的长度。
在归并排序中每一次递归都将数组分为两个大小相等或相差最多1的子数组。这个过程的时间复杂度是O(logn)因为每次递归都将数组的规模减半.
在合并操作中需要比较和合并两个子数组的元素。合并过程的时间复杂度是O(n)其中n是两个子数组的总长度。
因此总的时间复杂度可以表示为T(n) 2T(n/2) O(n)其中T(n/2)表示对两个子数组的递归调用O(n)表示合并操作的时间复杂度。
根据主定理Master Theorem的第三种情况可以得到归并排序的时间复杂度为O(nlogn)。
空间复杂度:
归并排序的空间复杂度是O(n)其中n是待排序数组的长度。
在归并排序的过程中需要创建一个临时数组来存储合并操作中的元素。这个临时数组的大小与待排序数组的长度相等因此需要额外的O(n)的空间来存储临时数组。
除了临时数组外归并排序的递归调用也会使用一定的栈空间。在每一层递归调用中需要保存一些变量和返回地址。由于归并排序的递归深度是O(logn)所以递归调用所使用的栈空间也是O(logn)的。
综上所述归并排序的总空间复杂度是O(n logn)简化后仍为O(n)。
需要注意的是在实际实现中如果原地排序可以避免创建临时数组将临时结果存储在原始数组中这样可以将空间复杂度优化为O(1)。但给定的代码中使用了额外的临时数组来存储合并操作的结果因此空间复杂度为O(n)。
思路和代码:
归并排序使用分治的思想将待排序的数组分割成较小的子数组直到子数组的长度为1或为空。通过递归调用归并排序对左右两个子数组进行排序直到所有子数组都被排序。将两个已排序的子数组合并成一个有序数组。在合并操作中创建一个临时数组比较两个子数组的元素并将较小的元素放入临时数组中。重复这个过程直到其中一个子数组的元素都放入了临时数组。如果其中一个子数组还有剩余的元素将剩余的元素复制到临时数组的末尾。将临时数组中的元素拷贝回原始数组的相应位置。重复以上步骤直到所有子数组都合并完成最终得到一个完全有序的数组。
#include iostream
#include vector
using namespace std;void merge(vectorint nums, int begin, int end, int midIndex)
{vectorint tmpArr(nums.begin() begin, nums.begin() end 1);int k 0;int b1 begin;int e1 midIndex;int b2 midIndex 1;int e2 end;while(b1 e1 b2 e2){if(nums[b1] nums[b2]){tmpArr[k] nums[b2];}else {tmpArr[k] nums[b1];}}while(b1 e1){tmpArr[k] nums[b1];}while(b2 e2){tmpArr[k] nums[b2];}for(int i 0; i tmpArr.size(); i){nums[i begin] tmpArr[i];}
}void process(vectorint nums, int left, int right)
{if(left right) return;// int mid (left right) / 2;int mid left (right - left) / 2;process(nums, left, mid);process(nums, mid 1, right);merge(nums, left, right, mid);
}void mergesort(vectorint nums)
{if(nums.size() 2) return;process(nums, 0, nums.size() - 1);
}
4.希尔排序
性能:
时间复杂度: O(N^1.3 ~ N^1.5)空间复杂度: O(1)稳定性: 不稳定原地排序
时间复杂度:
希尔排序的时间复杂度并不容易精确确定它取决于所选择的间隔序列。在最坏情况下希尔排序的时间复杂度为O(n^2)但在平均情况下其复杂度通常被认为是小于O(n^2)的。
希尔排序的时间复杂度分析比较复杂因为它涉及到不同的间隔序列和排序过程中的元素比较次数。最好的情况下当间隔序列满足特定条件时希尔排序可以达到接近O(n)的时间复杂度。但是一般来说希尔排序的时间复杂度介于O(n log n)和O(n^2)之间。
希尔排序的时间复杂度取决于选择的间隔序列的性质。常见的间隔序列包括希尔序列、Hibbard序列、Sedgewick序列等。不同的间隔序列会对排序过程中的比较次数产生影响进而影响时间复杂度的上界。
综合来说希尔排序的时间复杂度是一个开放问题没有一个确定的公式或界限。它的时间复杂度通常被认为是介于O(n log n)和O(n^2)之间。在实际应用中希尔排序通常比简单的插入排序具有更好的性能尤其对于较大规模的数据集。
空间复杂度:
希尔排序的空间复杂度是O(1)即不需要额外的空间来存储数据。希尔排序是一种原地排序算法它通过在原始数组上进行元素的比较和交换来进行排序不需要额外的辅助数组或数据结构。
希尔排序的排序过程中只涉及到有限的几个变量如间隔序列的增量、待插入的元素和临时变量用于交换元素位置。这些变量的空间占用是常数级别的与输入规模无关。
因此希尔排序的空间复杂度是O(1)即空间占用是固定的不随输入规模的增长而增加。这使得希尔排序在空间有限或对空间复杂度要求较高的情况下具有优势。
思路和代码:
这段代码实现了希尔排序算法它是插入排序的一种改进版本。希尔排序通过将数组分组进行插入排序并逐步缩小分组的间隔最终实现整体的排序。
初始化间隔gap为数组大小。在每次循环中将数组按照当前间隔进行分组对每个分组进行插入排序。逐步缩小间隔直到间隔为1完成最后一轮整体的插入排序。
在代码中shell函数实现了按照给定间隔进行分组的插入排序。它的主要逻辑是
从第gap个元素开始将当前元素视为待插入的元素。
将待插入元素与当前分组中的元素进行比较如果当前分组中的元素大于待插入元素则将该元素后移gap个位置。
重复步骤2直到找到小于等于待插入元素的位置。
将待插入元素插入到找到的位置后面。
在ShellSort函数中通过不断缩小间隔gap的值调用shell函数进行分组插入排序直到间隔为1完成最后一轮整体的插入排序。
#include iostream
#include vector
using namespace std;void shell(vectorint nums, int gap)
{// 这里的i需要for (int i gap; i nums.size(); i){int inserted nums[i];int j i - gap;for (; j 0; j - gap){if (nums[j] inserted){nums[j gap] nums[j];}else{break;}}nums[j gap] inserted;}
}void shellsort(vectorint nums)
{int gap nums.size();while (gap 1){shell(nums, gap);gap / 2;}// 最后整体看成一组进行直接插入排序shell(nums, 1);
}
5.选择排序
性能:
时间复杂度: O(N^2), 选择排序对数据不敏感, 不管数据是有序还是无序的时间复杂度都是N^2空间复杂度: O(1)稳定性: 不稳定
时间复杂度:
选择排序的时间复杂度为 O(n^2)其中 n 是数组的长度。
在每一轮循环中需要遍历无序区间来查找最小值的索引这个遍历的次数是一个等差数列其长度从 n-1 递减到 1。因此总的比较次数可以近似为 n-1 n-2 ... 2 1即等差数列的求和公式结果为 (n-1) * n / 2。这说明比较的次数与 n 的平方级别成正比。
除了比较操作选择排序还需要进行元素交换的操作每一轮循环最多进行一次交换。因此交换的次数也是与 n 成正比的。
综上所述选择排序的时间复杂度为 O(n^2)。即使在最好情况下每个元素都已经有序仍然需要进行 n-1 次比较因此时间复杂度仍然是 O(n^2)。选择排序的时间复杂度相对较高在大规模数据排序时不如其他高效的排序算法。
空间复杂度:
选择排序的空间复杂度为 O(1)即不需要额外的空间。
选择排序是在原地进行排序的算法它只需要使用常数级别的额外空间来存储临时变量和进行元素交换。无论输入数据规模的大小额外空间的使用量都保持不变因此空间复杂度是常数级别的 O(1)。这使得选择排序在空间有限的情况下也能有效地进行排序。
思路和代码:
选择排序的思路是在每一轮循环中选择无序区间中的最小值并将其放到有序区间的末尾直到所有元素有序。
遍历数组将数组分为有序区间和无序区间。初始时有序区间为空无序区间包含整个数组。
在无序区间中查找最小值的索引记录为 minIndex。
将找到的最小值与无序区间的第一个元素进行交换。
有序区间扩大一个元素无序区间缩小一个元素即有序区间的末尾增加一个元素无序区间的开头减少一个元素。
重复步骤2到步骤4直到无序区间为空。
该算法通过不断选择最小值并交换位置逐步将最小值放到有序区间的末尾使得有序区间不断扩大无序区间不断缩小最终实现整个数组的排序。
#include iostream
#include vector
using namespace std;// 版本一(一次找一个):
void selectsort(vectorint nums)
{// 从无序区间不断挑选出最小值. 挑选 n-1 次(最后一个元素不用挑)for (int i 0; i nums.size(); i){// i 下标左边已经排好序, 右边(包括 i)是无序的区间// 最小值下标默认是无序区间的第一个元素的下标int minIndex i;for (int j i 1; j nums.size(); j) // 找出最小值{if (nums[j] nums[minIndex]){minIndex j; // 更新最小值的下标}}myswap(nums, i, minIndex); // 交换最小值与无序区间的第一个元素}
}// 版本二(一次找俩个):
void selectsort2(vectorint nums)
{int left 0;int right nums.size() - 1;while (left right){int maxIndex left;int minIndex left;for (int i left 1; i right; i){if (nums[i] nums[maxIndex]){maxIndex i;}else if (nums[i] nums[minIndex]){minIndex i;}}myswap(nums, minIndex, left);//需要这个 if 判断, 否则存在bug//如果left下标的值就是最大值, 不加这个if, 就会导致找到的最大值下标(maxIndex)被篡改//案例: 18 3 10 2 7if (left maxIndex){maxIndex minIndex;}myswap(nums, maxIndex, right);left;right--;}
}
6.堆排序
性能:
时间复杂度: O(N*logN)空间复杂度: O(1)堆排序是不稳定的原地排序
时间复杂度:
堆排序的时间复杂度为O(NlogN)其中N是数组的大小。
建立堆的过程需要从最后一个非叶子节点开始对每个节点调用adjustDown函数时间复杂度为O(N)。
交换和调整的过程需要将根节点与最后一个节点交换然后再次调用adjustDown函数重复执行N-1次。每次调整的时间复杂度为O(logN)。因此总的时间复杂度为O(NlogN)。
空间复杂度:
堆排序的空间复杂度为O(1)即原地排序。
堆排序算法不需要额外的辅助空间来存储中间结果所有的操作都是在原始数组上进行的。只需要用到常数级别的额外空间来存储一些临时变量如父节点、子节点等而不随数组规模的增加而变化。
思路和代码:
adjustDown函数是向下调整的操作用于将最大的元素调整到堆顶。它接受一个数组 nums、堆的大小 size 和需要进行调整的父节点索引 parent。在该函数中首先通过计算获取父节点的左孩子索引 child。然后在循环中通过比较左右孩子的值选择较大的孩子节点。如果孩子节点的值大于父节点的值则交换它们并更新父节点和孩子节点的索引。最后如果孩子节点的值小于或等于父节点的值就跳出循环。这样就能够将最大的元素调整到堆顶。
heapsort函数是堆排序的主要实现。首先它检查数组的大小如果大小小于2则表示数组已经有序直接返回。接下来执行堆排序的两个主要步骤
建立大堆从倒数第一个非叶子节点开始依次对每个父节点调用adjustDown函数将数组调整为一个大堆。这个过程确保了每个父节点都大于或等于其子节点。
交换和调整从堆的根节点开始将根节点最大元素与堆的最后一个元素交换然后通过调用adjustDown函数将交换后的堆重新调整为大堆。然后继续将根节点与倒数第二个元素交换并再次调整堆。依此类推直到将所有元素都交换到适当的位置。
通过以上步骤堆排序能够按照从小到大的顺序对给定数组进行排序。堆排序具有时间复杂度为O(NlogN)其中N是数组的大小。它是一种原地排序算法因为只需要对原始数组进行原地交换而不需要额外的空间。
#include iostream
#include vector
using namespace std;// 大堆
// 向下调整
// 将最大的元素调整到堆顶
void adjustDown(vectorint nums, int size, int parent)
{int child 2 * parent 1;// 最起码保证有左孩子while (child size){// 看看有没有右孩子, 要是有再看看右孩子是不是大于左孩子, 大于就用右孩子和父节点比较if (child 1 size nums[child 1] nums[child]){child; // 选出左右孩子中最小的那个}if (nums[child] nums[parent]){myswap(nums, child, parent);parent child;child 2 * parent 1;}else{break;}}
}void heapsort(vectorint nums)
{if(nums.size() 2) return;// 1. 建大堆 O(N)// 将元素全部入完, 从 i 开始向下调整int N nums.size();// i 从倒数第一个非叶子节点开始// N-1 表示最后一个元素的下标, 再 -1 是为了实现由孩子节点找到父亲节点for (int i (N - 1 - 1) / 2; i 0; i--){adjustDown(nums, N, i);}// 2. 和堆顶元素做交换 O(N*logN)int end N - 1;while (end 0){myswap(nums, 0, end);adjustDown(nums, end, 0);end--;}
}
topK问题
选出最大的第K个, 建立小堆
选出最小的第K个, 建立大堆
#include iostream
#include vector
using namespace std;// 选出最大的前K个元素, 需要建小堆
// 这种方法只需要建立大小为K的堆即可, 节省空间
void myswap(vectorint nums, int a, int b)
{int tmp nums[a];nums[a] nums[b];nums[b] tmp;
}
// 向下调整
// 建小堆
void adjustDown(vectorint a, int size, int parent)
{int child 2 * parent 1;while (child size){if (child 1 size a[child 1] a[child]) // a[child 1] a[child]{ // 选出左右孩子中小的那个child;}if (a[child] a[parent]) // a[child] a[parent]{myswap(a, child, parent);parent child;child 2 * parent 1;}else{break;}}
}// Top-K问题(最大的前K个)
// 这是最优的topK, 空间复杂度很低
void topK(vectorint a, int k)
{// 1. 建堆 -- 用a中前k个元素建堆vectorint KMinHeap;for (int i 0; i k; i) // 将元素存入到数组中{KMinHeap.push_back(a[i]);}for (int i (k - 1 - 1) / 2; i 0; i--) // 建堆{adjustDown(KMinHeap, k, i);}// 2. 将剩余的n-k个元素和堆顶元素进行比较, 大于堆顶元素的就交换int N a.size();for (int i k; i N; i){if (a[i] KMinHeap[0]) // a[i] KMinHeap[0]{KMinHeap[0] a[i];adjustDown(KMinHeap, k, 0);}}for (int i 0; i k; i){printf(%d , KMinHeap[i]);}
}
7.快速排序
性能:
时间复杂度: O(N*logN)(平均情况), 最坏情况下O(N^2)空间复杂度: O(logN)(平均情况), 最坏情况下O(N)快排没有稳定性原地排序
时间复杂度:
快速排序的平均时间复杂度为 O(nlogn)其中 n 是待排序数组的长度。
在每一次快速排序的划分过程中数组被分为两个部分左侧部分的元素小于等于基准元素右侧部分的元素大于等于基准元素。这个过程的时间复杂度是 O(n)其中 n 是当前待排序数组的长度。
在平均情况下每次划分都将数组分成大致相等的两部分即左右子数组的规模大致为 n/2。这样如果我们假设每次划分花费的时间是常数那么在进行完 O(logn) 次划分后数组就会完全有序。因此平均情况下的时间复杂度为 O(nlogn)。
需要注意的是最坏情况下即每次划分后都使得数组中的一个子数组为空此时快速排序的时间复杂度为 O(n^2)。这种情况通常发生在输入数据已经有序或接近有序的情况下并且基准元素的选择不合适如选择的始终是最大或最小元素。为了避免最坏情况的发生可以采用随机化的方式选择基准元素。
综上所述快速排序的平均时间复杂度为 O(nlogn)最坏情况下的时间复杂度为 O(n^2)。在实践中快速排序通常具有较好的性能尤其对于大规模数据的排序。
空间复杂度:
快速排序的空间复杂度主要取决于递归调用的栈空间和基准元素的选择方式。
在最坏情况下即每次选择的基准元素都是当前子数组中的最大或最小值时快速排序的递归树将达到最大深度此时空间复杂度为 O(n)。每次递归调用都会在栈上创建一个新的帧直到递归结束后栈帧逐个弹出。
在平均情况下快速排序的递归树的平均深度为 O(logn)因此空间复杂度也为 O(logn)。这是因为每次递归调用时数组被分割成两个子数组每个子数组的规模大约是原数组的一半递归树的高度大约为 logn。
除了递归调用的栈空间外快速排序通常不需要额外的辅助空间。它是一种原地排序算法通过交换元素来进行排序不需要额外的数组或数据结构来存储中间结果。
需要注意的是如果使用随机化的方式选择基准元素即在每次排序时随机选择一个元素作为基准可以平衡地分割数组降低最坏情况出现的概率从而进一步减少空间复杂度的期望值。
综上所述快速排序的空间复杂度为 O(logn)平均情况和 O(n)最坏情况其中 n 是待排序数组的长度。
思路和代码:
快速排序核心思想是通过选择一个基准元素将数组分割成左右两个子数组其中左边的子数组元素都小于等于基准元素右边的子数组元素都大于等于基准元素然后对左右子数组递归地进行排序。
递归调用。对左右子数组分别进行递归调用快速排序直到子数组的长度小于等于1时终止递归。
合并结果。当递归调用结束后子数组都已经有序此时整个数组也就有序了。
荷兰国旗问题是快速排序算法的一种优化旨在处理数组中存在重复元素的情况。它的目标是将数组中的元素按照某个特定值进行分区使得分区后的数组满足以下条件
左边的子数组中的元素都小于特定值。中间的子数组中的元素都等于特定值。右边的子数组中的元素都大于特定值。
#include iostream
#include vector
#include cstdlib // 包含 rand 函数
using namespace std;vectorint netherlandsFlag(vectorint nums, int left, int right)
{if(left right) return { -1, -1 };if(left right) return { left, right };int less left - 1; // 左边界的前一个位置int more right; // 右边界int index left;while(index more){if(nums[index] nums[right]){myswap(nums, index, less);}else if(nums[index] nums[right]){myswap(nums, index, --more);}else{index;}}// 将基准元素放到等于区域的最后一个位置上将等于区域的边界返回作为分区点。myswap(nums, index, right);return { less 1, more};
}void process(vectorint nums, int left, int right)
{if(left right) return;int index left (int)(rand() % (right - left 1));myswap(nums, index, right);vectorint equalsArea netherlandsFlag(nums, left, right);process(nums, left, equalsArea[0] - 1);process(nums, equalsArea[1] 1, right);
}void quicksort(vectorint nums)
{if(nums.size() 2) return;process(nums, 0, nums.size() - 1);
} #include iostream
#include vector
#include stack
#include cstdlib // 包含 rand 函数
#include algorithm // 包含 swap 函数
using namespace std;/* 快排-非递归 */
vectorint netherlandsFlag(vectorint nums, int left, int right)
{if (left right) return { -1, -1 };if (left right) return { left, right };int less left - 1;int more right;int index left;while (index more){if(nums[index] nums[right]){myswap(nums, index, less);}else if(nums[index] nums[right]){myswap(nums, index, --more);}else{index;}}// 将基准元素放到等于区域的最后一个位置上将等于区域的边界返回作为分区点。myswap(nums, index, right);return { less 1, more };
}void quicksort(vectorint nums)
{if (nums.size() 2) return;stackpairint, int st;st.push(make_pair(0, nums.size() - 1));while (!st.empty()){int left st.top().first;int right st.top().second;/*当我们处理完一个子数组时该子数组已经被完全排序不再需要进一步的处理。因此我们需要将其从栈中移除以便下一轮循环时可以取出下一个待处理的子数组。*/st.pop();if (left right) continue;int index left rand() % (right - left 1);myswap(nums, index, right);vectorint equalsArea netherlandsFlag(nums, left, right);st.push(make_pair(left, equalsArea[0] - 1));st.push(make_pair(equalsArea[1] 1, right));}
} 文章转载自: http://www.morning.cczzyy.com.gov.cn.cczzyy.com http://www.morning.bbgn.cn.gov.cn.bbgn.cn http://www.morning.jjmrx.cn.gov.cn.jjmrx.cn http://www.morning.wrlxt.cn.gov.cn.wrlxt.cn http://www.morning.dljujia.com.gov.cn.dljujia.com http://www.morning.rqqlp.cn.gov.cn.rqqlp.cn http://www.morning.hrjrt.cn.gov.cn.hrjrt.cn http://www.morning.lpcpb.cn.gov.cn.lpcpb.cn http://www.morning.xinxianzhi005.com.gov.cn.xinxianzhi005.com http://www.morning.wxlzr.cn.gov.cn.wxlzr.cn http://www.morning.qbksx.cn.gov.cn.qbksx.cn http://www.morning.zrqs.cn.gov.cn.zrqs.cn http://www.morning.ljfjm.cn.gov.cn.ljfjm.cn http://www.morning.nrydm.cn.gov.cn.nrydm.cn http://www.morning.mnbcj.cn.gov.cn.mnbcj.cn http://www.morning.ksqzd.cn.gov.cn.ksqzd.cn http://www.morning.etsaf.com.gov.cn.etsaf.com http://www.morning.cldgh.cn.gov.cn.cldgh.cn http://www.morning.lbgfz.cn.gov.cn.lbgfz.cn http://www.morning.tytly.cn.gov.cn.tytly.cn http://www.morning.xdxpq.cn.gov.cn.xdxpq.cn http://www.morning.rbcw.cn.gov.cn.rbcw.cn http://www.morning.snnb.cn.gov.cn.snnb.cn http://www.morning.qdrhf.cn.gov.cn.qdrhf.cn http://www.morning.htmhl.cn.gov.cn.htmhl.cn http://www.morning.mdpkf.cn.gov.cn.mdpkf.cn http://www.morning.fqqlq.cn.gov.cn.fqqlq.cn http://www.morning.hmfxl.cn.gov.cn.hmfxl.cn http://www.morning.zrdhd.cn.gov.cn.zrdhd.cn http://www.morning.xbptx.cn.gov.cn.xbptx.cn http://www.morning.hhpbj.cn.gov.cn.hhpbj.cn http://www.morning.rhfbl.cn.gov.cn.rhfbl.cn http://www.morning.cwnqd.cn.gov.cn.cwnqd.cn http://www.morning.sbczr.cn.gov.cn.sbczr.cn http://www.morning.fnczn.cn.gov.cn.fnczn.cn http://www.morning.wqmyh.cn.gov.cn.wqmyh.cn http://www.morning.psgbk.cn.gov.cn.psgbk.cn http://www.morning.qpqwd.cn.gov.cn.qpqwd.cn http://www.morning.mbrbg.cn.gov.cn.mbrbg.cn http://www.morning.bzjpn.cn.gov.cn.bzjpn.cn http://www.morning.twdkt.cn.gov.cn.twdkt.cn http://www.morning.pqkyx.cn.gov.cn.pqkyx.cn http://www.morning.zrpbf.cn.gov.cn.zrpbf.cn http://www.morning.lqzhj.cn.gov.cn.lqzhj.cn http://www.morning.lqlhw.cn.gov.cn.lqlhw.cn http://www.morning.yrnrr.cn.gov.cn.yrnrr.cn http://www.morning.rfpb.cn.gov.cn.rfpb.cn http://www.morning.ryxbz.cn.gov.cn.ryxbz.cn http://www.morning.llxyf.cn.gov.cn.llxyf.cn http://www.morning.ltxgk.cn.gov.cn.ltxgk.cn http://www.morning.rfjmy.cn.gov.cn.rfjmy.cn http://www.morning.xczyj.cn.gov.cn.xczyj.cn http://www.morning.tmnyj.cn.gov.cn.tmnyj.cn http://www.morning.hkshy.cn.gov.cn.hkshy.cn http://www.morning.gslz.com.cn.gov.cn.gslz.com.cn http://www.morning.qwbls.cn.gov.cn.qwbls.cn http://www.morning.rjmd.cn.gov.cn.rjmd.cn http://www.morning.yrdt.cn.gov.cn.yrdt.cn http://www.morning.gbtty.cn.gov.cn.gbtty.cn http://www.morning.xqspn.cn.gov.cn.xqspn.cn http://www.morning.jmdpp.cn.gov.cn.jmdpp.cn http://www.morning.ymjgx.cn.gov.cn.ymjgx.cn http://www.morning.gqflj.cn.gov.cn.gqflj.cn http://www.morning.yzmzp.cn.gov.cn.yzmzp.cn http://www.morning.fhtmp.cn.gov.cn.fhtmp.cn http://www.morning.nkkpp.cn.gov.cn.nkkpp.cn http://www.morning.rbnj.cn.gov.cn.rbnj.cn http://www.morning.lhxrn.cn.gov.cn.lhxrn.cn http://www.morning.lxkhx.cn.gov.cn.lxkhx.cn http://www.morning.fylsz.cn.gov.cn.fylsz.cn http://www.morning.pzjfz.cn.gov.cn.pzjfz.cn http://www.morning.gydth.cn.gov.cn.gydth.cn http://www.morning.rkjz.cn.gov.cn.rkjz.cn http://www.morning.rksnk.cn.gov.cn.rksnk.cn http://www.morning.lmmkf.cn.gov.cn.lmmkf.cn http://www.morning.cczzyy.com.gov.cn.cczzyy.com http://www.morning.tgdys.cn.gov.cn.tgdys.cn http://www.morning.hprmg.cn.gov.cn.hprmg.cn http://www.morning.hjssh.cn.gov.cn.hjssh.cn http://www.morning.wbdm.cn.gov.cn.wbdm.cn