1、快速排序
把快速排序放第一个是因为这个排序算法使用频率很高,快速排序是一种分而治之思想在排序算法上的典型应用,把一个序列分为两个子序列。
第一种实现方式
#include<iostream>
#include<algorithm>begin
using namespace std;
#include<vector>
void quickSort1(vector<int>& num, int begin, int end) {
//说明已经有序,直接返回
if (begin >= end)
return;
int pivot = num[begin]; //pivot称为基准,一开始把基准定为起始位置
int i = begin, j = end;
while (i < j) {
while (i < j && num[j] >= pivot) {
j--; //从后往前遍历,说明原位置是合理的,就j--
}
if (i < j)
num[i++] = num[j]; //若num[j] < pivot,把该元素提前,且i++
while (i < j && num[i] <= pivot) {
i++; //从前往后遍历,说明原位置是合理的,就i++
}
if (i < j)
num[j--] = num[i]; //若num[i] > pivot,把该元素滞后,且j--
}
num[i] = pivot; //因为前面遍历完之后,i = j = 元素中间位置,所以把基准位置放到中间
quickSort1(num, begin, i - 1); //递归基准的前半部分
quickSort1(num, i + 1, end); //递归基准的后半部分
//递归的结束标志,是数列的大小是零或一,begin <= (i - 1),也就是已经被排序好了
}
第二种实现方式
void quickSort2(vector<int>& num, int begin, int end) {
//说明已经有序,直接返回
if (begin >= end)
return;
int i = begin - 1, j = end + 1; //这样定义i,j是方便后面使用就j--,i++
int pivot = num[begin + end >> 1]; //pivot取中间值,也可以定义成从元素中随机取
while (i < j)
{
do j--;
while (num[j] > pivot); //说明num[j]的位置是合理的,j--
do i++;
while (num[i] < pivot); //说明num[i]的位置是合理的,i++
if (i < j) //走if语句,说明i < j,如果i>=j,走递归函数,自动退出while循环
{
swap(num[i], num[j]); //num[i],num[j]位置不合理,交换位置
}
else //自动退出while循环
{
quickSort2(num, begin, j);
quickSort2(num, j + 1, end);
}
}
}
2、冒泡排序
第一种实现方式
#include<iostream>
#include<algorithm>begin
using namespace std;
#include<vector>
void bubbleSort1(vector<int>& nums) {
int len = nums.size();
for (int i = 0; i < len; ++i) {
for (int j = 0; j + 1< len - i; ++j) {
if (nums[j] > nums[j + 1])
swap(nums[j], nums[j + 1]);
}
}
}
第二种实现方式
优化:对于数组已经是有序的了,我们无需再对剩余的元素重复比较下去
void bubbleSort2(vector<int>& nums) {
int len = nums.size();
bool flag = false;
for (int i = 0; i < len - 1; ++i) {
flag = false;
for (int j = 0; j + 1 < len - i; ++j) {
if (nums[j] > nums[j + 1])
{
swap(nums[j], nums[j + 1]);
flag = true;
}
}
//若某一趟中一次元素交换都没有,即依然为flag = false
//那么表明所剩待排序列已经有序,不必再进行趟数比较,外层循环应该结束,跳出循环
if (!flag)
break;
}
}
3、选择排序
#include<iostream>
#include<algorithm>begin
using namespace std;
#include<vector>
void selectSort(vector<int>& num) {
int len = num.size();
int minIndex = 0;
for (int i = 0; i < len; i++) {
minIndex = i;
for (int j = i + 1; j < len; j++)
{
if (num[j] < num[minIndex])
minIndex = j; //遍历完之后,将最小元素的下标记录下来
}
swap(num[i], num[minIndex]); //交换当前位置的元素为最小值
}
}
4、插入排序
#include<iostream>
#include<algorithm>
using namespace std;
#include<vector>
void insertSort(vector<int>& num) {
int len = num.size();
for (int i = 1; i < len; i++)
{
// 记录要插入的数据
int temp = num[i];
// 若第i个元素大于i-1元素,不需要变化。小于的话,移动有序表后插入
int j = i;
while (j > 0 && temp < num[j - 1]) //从已经排序的序列最右边的开始比较,num[j - 1]是要插入数据的前一个元素
{
num[j] = num[j - 1]; //将前面有序子数列往后挪,找到被插元素的下标记录为j
j--;
}
// 如果j != i 那么被插元素一定小于前面有序表的某些元素
if (j != i) {
num[j] = temp;
}
}
}
5、归并排序
算法采用经典的分治策略(分治法将问题分(divide)成一些小的问题然后递归求解
ps:与快速排序不同,快速排序是先确定一个数组里面的值,pivot = num[begin]
------而归并排序确定的是中间元素的这个下标位置,mid = (begin + end) / 2
void mergeSort(vector<int>& num, int begin, int end) {
if (begin >= end)
return;
int mid = (begin + end) / 2;
mergeSort(num, begin, mid); //先递归得到最小左子序列,进行排序
mergeSort(num, mid + 1, end); //先递归得到最小右子序列,进行排序
static vector<int> temp; //static定义的temp看成全局变量
temp.clear();
//归并操作
int i = begin, j = mid + 1;
while (i <= mid && j <= end) //当i和j都没有超过各自的序列size时,比较左右序列的元素大小分别放入temp中
{ //当其中一个下标已经越界后,另一个序列就不需要比了,直接抄到temp中
if (num[i] <= num[j])
temp.push_back(num[i++]); //a:左 < 右,把左边的元素放到temp中
else
temp.push_back(num[j++]); //b:左 > 右,把右边的元素放到temp中
}
while (i <= mid)
temp.push_back(num[i++]); //b:把左边剩下的元素直接抄到temp中
while (j <= end)
temp.push_back(num[j++]); //a:把右边剩下的元素直接抄到temp中
//将合并好的有序数列还回去
for (i = begin, j = 0; j < (int)temp.size(); i++, j++)
num[i] = temp[j];
}
测试
int main01()
{
vector<int> num = { 8,7,1,4,2,3,9,6,8,5 };
quickSort1(num, 0, num.size() - 1);
quickSort2(num, 0, num.size() - 1);
bubbleSort1(num);
bubbleSort2(num);
selectSort(num);
insertSort(num);
mergeSort(num, 0, num.size() - 1);
for (auto i : num) {
cout << i << " ";
}
cout << endl;
return 0;
}