C++实现几种常见的排序算法(上)

在这里插入图片描述

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;
}

参考:
归并排序
十大经典排序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值