排序(6)——冒泡排序、计数排序

七、冒泡排序

1.简介

        冒泡排序可以说是我们的老朋友了,是一种很简单的排序方法。冒泡就是泡泡在水中向上漂,很形象的名字和贴合它的思路,通过一趟趟的冒泡每一次将最大的元素冒到最后的位置处,这样就完成了数据的排序。

2.思路与代码

        冒泡排序无需多言,就是比较相邻元素大小,将较大者不断后移。我们在以前的博客中介绍过冒泡排序,http://t.csdnimg.cn/sB0Yp,有需要可以去瞧瞧哈

void BubbleSort(int* a, int n)
{
	for (int j = 0; j < n; j++)
	{
		bool flag = true;
		for (int i = 0; i < n - 1 - j; i++)
		{
			if (a[i] > a[i + 1])
			{
				swap(&a[i], &a[i + 1]);
				flag = false;
			}
		}
		if (flag)
		{
			break;
		}
	}
}

3.复杂度与稳定性分析

(1)时间复杂度

        冒泡排序时间复杂度不难计算,由于我们加入了flag作为判断,所以当为顺序的情况时只需要遍历一遍,其时间复杂度是O(n)。而逆序是最差情况,是个标准的等差数列,时间复杂度为O(n^2)

        一般认为冒泡排序的时间复杂度是O(n^2)

(2)空间复杂度

        冒泡排序没有使用额外的空间,其空间复杂度为O(1)

(3)稳定性

        冒泡排序是稳定的。

        冒泡排序比较相邻元素并进行交换,这就意味着相对位置在前的元素想要换到相对位置在后的元素后面,必须要越过这个靠后的元素,即二者一定会存在比较。只需要限定一下当一次比较时二者相等不进行交换,这样就可以保证稳定性。

八、计数排序

1.简介

        计数排序给我的感觉就是众多排序算法中的民间高手。虽然方法不入流,适用范围不广,但是架不住它真的快。排序算法简单说就是统计所有数据出现的次数,然后根据统计的次数从小到大再将数据依次输出。说它不入流是因为我感觉计数排序并非真正的排序,这种统计次数再输出的方式并不是对于原数组进行数据的处理,这也就注定了它的适用范围并不会很广。计数排序只能用于数据跨度较小的整数排序上。

2.思路与代码

        计数排序使用一个计数数组来记录数组过程中各个元素出现的次数,计数数组的下标代表着各种值,下标位置存储的数据则是出现次数。

        为了节约空间与拓展统计区间,我们一般会先遍历数组找到最大值和最小值。根据这个最大值和最小值得到所需要统计数据的区间,并以此为依据进行数组开辟。同时可以将最小值设置为偏移量,根据最小值的大小确定数组0下标位置存储的数据是谁的。

        之后再遍历数组进行计数,然后再遍历计数数组进行数据写出即可。

void CountSort(int* a, int n)
{
	//找到偏移量
	int min = a[0], max = a[0];
	for (int i = 0; i < n; i++)
	{
		if (a[i] < min)
		{
			min = a[i];
		}
		if (a[i] > max)
		{
			max = a[i];
		}
	}

	int range = max - min + 1;

	int* cou = (int*)calloc(range, sizeof(int));
	if (cou == NULL)
	{
		perror("calloc fail");
		return;
	}

	//计数
	for (int i = 0; i < n; i++)
	{
		cou[a[i] - min]++;
	}
	//排序
	int k = 0;
	for (int i = 0; i < range; i++)
	{
		for (int j = 0; j < cou[i]; j++)
		{
			a[k++] = i + min;
		}
	}
}

3.复杂度与稳定性分析

(1)时间复杂度

        对于计数排序,假设其跨度为m,它存在着三次遍历,前两次是对原数组的遍历(n),最后一次是对计数数组与其值的遍历(n+m)。因此其时间复杂度与数据规模n和数据跨度m都有关系,时间复杂度为O(n+m)

(2)空间复杂度

        计数排序使用了计数数组,计数数组的规模是根据待排序数组的跨度m而定的,所以其空间复杂度为O(m)

(3)稳定性

        计数排序是稳定的。

        对于计数排序而言,因为我们是遍历其原数组进行对计数数组的写入再输出,根据遍历访问的先后顺序我们是有办法控制其稳定的,如利用队列等控制同一个值的先入先出。指的一提的是稳定性的意义更多用于复杂对象,我们根据其某一个指标排序而维持此前的相对位置,所以如果需要稳定的计数排序,以我现在的水平来说,我会选择使用队列来存储每个计数背后的复杂对象来实现先进先出。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

犀利卓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值