数据结构与算法之美_11_排序

需要掌握的8个排序算法

冒泡排序、插入排序、选择排序、归并排序、快速排序、计数排序、基数排序、桶排序。
在这里插入图片描述

学习排序算法需要掌握什么?

1、算法思想
2、代码实现
3、算法执行效率

思考

插入排序和冒泡排序的时间复杂度相同,都是 O(n2),在实际的软件开发里,为什么我们更倾向于使用插入排序算法而不是冒泡排序算法呢?

冒泡排序(Bubble Sort)

一、什么是冒泡排序?
对一组数据进行排序,一次冒泡是依次比较相邻的两个数据,若满足顺序要求则不对元素进行交换,若不满足排序要求,怎交换元素位置。
1、具有n个元素的一组数据,最多需要进行n次冒泡
2、每次冒泡需要进行n-1次比较
3、若某次冒泡中没有发生元素的交换,说明这组数据已经有序,因此不需要继续后面的冒泡

int * bubble_sort(int n, int * a)
{
	if (n <= 1)
	{
		return nullptr;
	}
	
	int tmp = 0;
	for (int i = 0; i < n; n++)
	{
		bool flag = false;
		for (int j = 0; j < n - j - 1; ++j)
		{
			if (a[j] > a[j + 1])
			{
				tmp = a[j];
				a[j] = a[j + 1];
				a[j + 1] = tmp;
				flag = true;
			}
		}
		if (flag == false)
		{
			break;
		}
	}
	return a;
}

二、冒泡排序的其他特性:
1、冒泡排序是原地排序,只需要常量级的临时空间,所以它的空间复杂度为 O(1),是一个原地排序算法
2、冒泡排序是稳定排序,因为如果两个元素相等不会发生交换

三、评估时间复杂度
冒泡排序的最好情况时间复杂度:O(n) , 元素有序的情况下
冒泡排序的最坏情况时间复杂度:O(n^2),倒序的情况下
冒泡排序的平均情况下的时间复杂度就是: O(n^2)

四、引入有序度、逆序度、满有序度的概念评估平均情况时间复杂度:
有序度:一组元素中有序的元素对的个数
满有序度:一个完全有序的数组的有序度 n*(n-1)/2
逆序度:一组数据排序后需要交换元素的次数
逆序度 = 满有序度 - 有序度

插入排序(Insertion Sort)

一、什么是插入排序?
首先我们将一组待排序的数据分为已排序区间和未排序区间。对于一组数据它的初始已排序区间只有一个元素, 每次从未排序区间中拿出一个元素插入到已排序区间,使得有序区间始终有序。直到未排序区间中的元素为空,排序结束。

int * intertion_sort(int n, int a[])
{
	if (n <= 1)
	{
		return nullptr;
	}
	int value = 0;
	for (int i = 1; i < n; i++)
	{
		value = a[i];
		int j = i - 1;
		for (; j >= 0; --j)
		{
			if (a[j] > value)
			{
				a[j + 1] = a[j];
			}
			else
			{
				break;
			}
		}
		a[j + 1] = value;
	}

	return a;
}

二、插入排序的一些特性
插入排序是原地排序,空间复杂度为O(1)
在插入排序中,对于值相同的元素,我们可以选择将后面出现的元素,插入到前面出现元素的后面,这样就可以保持原有的前后顺序不变,所以插入排序是稳定的排序算法。

三、插入排序的时间复杂度
最好情况时间复杂度: O(n) ,在数据有序的情况下,每次只需要比较一次就能找到插入点将后面的数据插入
最坏情况时间复杂度:O(n^2) 如果数组是倒序的,每次插入都相当于在数组的第一个位置插入新的数据,所以需要移动大量的数据。
平均情况时间复杂度:还记得我们在数组中插入一个数据的平均时间复杂度是多少吗?没错,是 O(n)。所以,对于插入排序来说,每次插入操作都相当于在数组中插入一个数据,循环执行 n 次插入操作,所以平均时间复杂度为 O(n^2)。

选择排序

一、选择排序的算法思路
选择排序算法的实现思路有点类似插入排序,也分已排序区间和未排序区间。但是选择排序每次会从未排序区间中找到最小的元素,将其放到已排序区间的末尾。

int * selection_sort(int a[], int n)
{
	int i, j, min_idx;
	for (i = 0; i < n; i++)
	{
		min_idx = i;
		for (j = i + 1; j < n; j++)
		{
			if (a[j] < a[min_idx])
			{
				min_idx = j;
			}
		}
		// 交换
		int tmp = 0;
		tmp = a[i];
		a[i] = a[min_idx];
		a[min_idx] = tmp;

	}
	return a;
}

二、选择排序的时间复杂度
最好情况时间复杂度:O(n^2)
最坏情况时间复杂度:O(n^2)
平均情况时间复杂度:O(n^2)

三、选择排序的其他特性
1、是原地排序
2、不是稳定排序

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值