几种排序算法

目录

冒泡排序

冒泡排序的思想

冒泡排序的实现

例题 蓝桥OJ3225 宝藏排序1

 问题描述

输入描述

输出描述

样例输入

样例输出

快速排序

快速排序的思想

快速排序的实现

例题 蓝桥oj 宝藏排序2

 问题描述

输入描述

输出描述

样例输入

样例输出

归并排序

归并排序的思想

归并排序的实现

选择排序

选择排序的思想

选择排序的实现

插入排序

插入排序的思想

插入排序的实现


冒泡排序

冒泡排序的思想

每次将最大的一次一次的运到最右边,然后将最右边这个确定下来。再确定第二大的、第三大的...

对于数组a[],具体来说,每次确定操作就是从左往右扫描,如果a[i]>a[i+1],我们就执行swap(a[i],a[i+1])将两项交换,然后再往右检查,这样可以找出最大的并将其丢到最右边。

第一次确定操作是将a[1]~a[n]中最大的放到a[n];

第二次确定操作是将a[1]~a[n-1]中最大的放到a[n-1];

以此类推,时间复杂对为O(n^2)

由于排序过程中,数字向冒泡泡一样从左往右换过去,故名为冒泡排序

冒泡排序的实现

#include
using namespace std;
const int N = 1e3 + 9;
int a[N];
int main()
{
	int n; cin >> n;
	for (int i = 1; i <= n; ++i)cin >> a[i];
	//i表示当前要确定的位置
	for (int i = n; i >= 1; --i)
	{
		//j从左往右扫
		for (int j = 1; j <= i - 1; ++j)
		{
			if (a[j] > a[j + 1])swap(a[j], a[j + 1]);
		}
	}
	return 0;
}

例题 蓝桥OJ3225 宝藏排序1

 问题描述

注意:这道题于宝藏排序Ⅰ的区别仅是数据范围

在一个神秘的岛屿上,有一支探险队发现了一批宝藏,这批宝藏是以整数数组的形式存在的。每个宝藏上都标有一个数字,代表了其珍贵程度。然而,由于某种神奇的力量,这批宝藏的顺序被打乱了,探险队需要将宝藏按照珍贵程度进行排序,以便更好地研究和保护它们。作为探险队的一员,肖恩需要设计合适的排序算法来将宝藏按照珍贵程度进行从小到大排序。请你帮帮肖恩。

输入描述

输入第一行包括一个数字 n ,表示宝藏总共有 n 个。

输入的第二行包括 n 个数字,第 i 个数字 a[i] 表示第 i 个宝藏的珍贵程度。

数据保证 1≤n≤1000,1≤a[i]≤10^6 。

输出描述

输出 n 个数字,为对宝藏按照珍贵程度从小到大排序后的数组。

样例输入

5
1 5 9 3 7

样例输出

1 3 5 7 9
#include 
using namespace std;
const int N = 1010;
int a[N];
int main()
{
	// 请在此输入您的代码
	int n; cin >> n;
	for (int i = 1; i <= n; ++i)cin >> a[i];
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j < i; j++)
		{
			if (a[i] < a[j])swap(a[i], a[j]);
		}
	}
	for (int i = 1; i <= n; i++)cout << a[i] << ' ';
	return 0;
}

快速排序

快速排序的思想

快速排序是一种基于分治法的排序方法,原理是将一个数组分成两个子数组,其中一个子数组的所有元素都小于另一个子数组的元素,然后递归地对这两个子数组进行排序。

快速排序的思想是通过不断的将数组分成两个子数组,递归的对子数组进行排序,最终得到一个有序的数组。这个过程通过选择合适的基准和分区操作来实现。

快速排序具有更好的时间复杂度O(nlogn),且不需要额外空间。

快速排序的实现

void QuickSort(int a[],int l,int r)
{
    if(l

这是快速排序的递归主体QuickSort() 传入参数要排序的数组和区间的左右端点

Partition函数会将数组a[l]~a[r]这个区间中某个基准数字放到正确的位置并将这个位置返回

在确定了mid的位置之后,可以保证a[l]~a[mid-1]都

 

int partition(int a[], int l, int r)
{
	int pivot = a[r];
	int i = l, j = r;
	while (i < j)
	{
		while (i < j && a[i] <= pivot)i++;
		while (i < j && a[j] >= pivot)j--;
		if (i < j)swap(a[i], a[j]);
		else swap(a[i], a[r]);
	}
	return 0;
}

例题 蓝桥oj 宝藏排序2

 问题描述

注意:这道题于宝藏排序Ⅰ的区别仅是数据范围

在一个神秘的岛屿上,有一支探险队发现了一批宝藏,这批宝藏是以整数数组的形式存在的。每个宝藏上都标有一个数字,代表了其珍贵程度。然而,由于某种神奇的力量,这批宝藏的顺序被打乱了,探险队需要将宝藏按照珍贵程度进行排序,以便更好地研究和保护它们。作为探险队的一员,肖恩需要设计合适的排序算法来将宝藏按照珍贵程度进行从小到大排序。请你帮帮肖恩。

输入描述

输入第一行包括一个数字 n ,表示宝藏总共有 n 个。

输入的第二行包括 n 个数字,第 i 个数字 a[i] 表示第 i 个宝藏的珍贵程度。

数据保证 1≤n≤10^5,1≤a[i]≤10^9 。

输出描述

输出 nn 个数字,为对宝藏按照珍贵程度从小到大排序后的数组。

样例输入

5
1 5 9 3 7

样例输出

1 3 5 7 9

#include 
using namespace std;
const int N = 1e5 + 9;
int a[N];

int partition(int a[], int l, int r)
{
	int pivot = a[r], i = l, j = r;
	while (i < j)
	{
		while (i < j && a[i] <= pivot)i++;
		while (i < j && a[j] >= pivot)j--;
		if (i < j)swap(a[i], a[j]);
		else swap(a[i], a[r]);
	}
	return i;
}

void QuickSort(int a[], int l, int r)
{
	if (l < r)
	{
		int mid = partition(a, l, r);
		QuickSort(a, l, mid - 1);
		QuickSort(a, mid + 1, r);
	}
}


int main()
{
	int n; cin >> n;
	for (int i = 1; i <= n; ++i)cin >> a[i];
	QuickSort(a, 1, n);

	for (int i = 1; i <= n; ++i)cout << a[i] << " \n"[i == n];
	// 请在此输入您的代码
	return 0;
}

归并排序

归并排序的思想

归并排序基于分治法的排序。

原理是将一个数组分成两个子数组,将子数组向下递归的排序后,得到两个有序数组,然后进行O(n)的合并,最终合并成有序的原数组。

时间复杂度为O(nlogn),但需要额外的空间用于合并数组。

归并排序的实现

void MergeSort(int a[], int l, int r)
{
	if (l == r)return;
	int mid = (l + r) / 2;
	MergeSort(a, l, mid);
	MergeSort(a, mid + 1, r);
	int pl = l, pr = mid + 1, pb = 1;
	while (p1 <= mid || pr <= r)
	{
		if (pl > mid)
		{
			b[pb++] = a[pr++];
		}
		else if (pr > r)
		{
			b[pb++] = a[pl++];
		}
		else
		{
			if (a[pl] > a[pr])b[pb++] = a[pl++];
			else b[pb++] = a[pr++];
		}
	}
	for (int i = l; i <= r; i++)a[i] = b[i];
}

选择排序

选择排序的思想

选择排序的思想和冒泡排序类似,是每次找出最大的然后直接放到右边对应位置,然后将最右边这个确定下来(而不是一个一个地交换过去)。再来确定第二大的,再确定第三大的..

对于数组a[],具体的来说,每次确定操作(假设当前要确定的是i位置)就是从左往右扫描计算出最大元素的下标max_id,最后执行一次swap(a[max_id],a[i])将两项交换即可。

第一次确定操作是将a[1]~a[n]中最大的放到a[n];第二次确定操作是将a[1]~a[n-1]中最大的放到a[n-1]。依此类推,时间复杂度为O(n^2)

选择排序的实现

#include
using namespace std;
const int N = 1e3 + 9;
int a[N];
int main()
{
	int n; cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
	for (int i = n; i >= 1; i--)
	{
		int max_id = 1;
		for (int j = 1; j <= i; j++)
		{
			if (a[j] > a[max_id])max_id = j;
		}
		swap(a[max_id], a[i]);
	}
	return 0;
}

插入排序

插入排序的思想

插入排序是一种简单直观的排序算法,其基本思想是将待排序的元素逐个插入到已排序序列的合适位置中,使得已排序序列逐渐扩大,从而逐步构建有序序列,最终得到完全有序的序列。
它类似于我们打扑克牌时的排序方式,将一张张牌插入到已经有序的手牌中。
时间复杂度为O(n^2)。

插入排序的实现

for (int i = 2; i <= n; ++i)
{
	int val = a[i], j;
	for (j = i; j > 1 && val < a[j - 1]; --j)
	{
		a[j] = a[j - 1];
	}
	a[j] = val;
 }

你可能感兴趣的:(排序算法,算法,数据结构)