排序算法——冒泡排序和选择排序

文章目录

  • 1.冒泡排序
    • 1.1冒泡排序的思想
    • 1.2冒泡排序性能分析
    • 1.3冒泡排序源代码
    • 1.4思考:冒泡排序的优化
      • 1.4.1优化代码
      • 1.4.2 冒泡优化前后的比较
    • 1.5主函数与显示函数
      • 1.5.1 注:
  • 2.选择排序
    • 2.1选择排序的思想
    • 2.2选择排序的性能分析
    • 2.3选择排序源代码
    • 2.4运行结果
    • 2.5主函数与显示函数
  • 3.总结

1.冒泡排序

希望大家能够给一个关注,我会努力写好每一篇文章的

1.1冒泡排序的思想

每一趟排序,从左向右两两比较,如果左边大于(为了排序的稳定性,是大于而不是大于等于)右边则两两交换,否则不交换(默认为升序排列)
排序算法——冒泡排序和选择排序_第1张图片

1.2冒泡排序性能分析

  • 冒泡排序 时间复杂度O(n^2) 空间复杂度O(1)
  • 稳定性:稳定

1.3冒泡排序源代码

//冒泡排序  时间复杂度O(n^2)  空间复杂度O(1)   稳定性:稳定
void Bubble_Sort(int *arr, int len)
{
	for(int i=0; i<len-1; i++)//控制循环趟数  len-1趟
	{
		for(int j=0; j+1<len-i; j++)//控制每一趟具体的比较过程   j代表两两比较的左值下标 两两比较的右值下标j+1
		{
			//从左向右 两两比较,如果左值大于右值 则交换
			if(arr[j] > arr[j+1])
			{
				int tmp = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = tmp;
			}
		}
	}
}

1.4思考:冒泡排序的优化

如果在第i次比较后,整个排序序列为有序序列时,按上述代码,仍然要将剩余轮数比较结束,这就是可以优化的点。
设置一个标记flag,当循环中没有元素相互交换时就跳出循环

1.4.1优化代码

//冒泡的优化
void Bubble_Sort2(int *arr, int len)
{
	for(int i=0; i<len-1; i++)//控制循环趟数  len-1趟
	{
		bool tag = true;//下一个标记
		for(int j=0; j+1<len-i; j++)//控制每一趟具体的比较过程   j代表两两比较的左值下标 两两比较的右值下标j+1
		{
			//从左向右 两两比较,如果左值大于右值 则交换
			if(arr[j] > arr[j+1])
			{
				int tmp = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = tmp;

				tag = false; //如果存在交换 则标价修改为假
			}
		}

		if(tag)//如果此时tag这个标记还是true,则代表这一趟排序没有左右交换过一次,也就代表着完全有序
		{
			//return;
			break;
		}

	}
}

1.4.2 冒泡优化前后的比较

优化前:我们将标记注释掉,定义一个count计数器来统计函数比较的次数,在函数中将其打印出来,结果如下图
排序算法——冒泡排序和选择排序_第2张图片
优化后
排序算法——冒泡排序和选择排序_第3张图片

  • 结论:比较可知,冒泡排序的优化幅度不大,但这确实是他的一种优化方法

1.5主函数与显示函数

void show(int* arr,int len)
{
	for (int i = 0; i < len; i++)
	{
		printf("%d ", arr[i]);
	}
}
int main()
{
	int arr[] = { -43,57,-71,47,3,30,-85,6,60,-59,0,-46,-40,-73,53,68,-82,-54,88,73,20,-89,-22,39,55,-26,95,-87,-57,-86,28,-37,43,-27,-24,-88,-35,82,-3,39,-85,-46,37,45,-24,35,-49,-27,-96,89,87,-62,85,-44,64,78,14,59,-55,-10,0,98,50,-75,11,97,-72,85,-68,-76,44,-12,76,76,8,-75,-64,-57,29,-24,27,-3,-45,-87,48,10,-13,17,94,-85,11,-42,-98,89,97,-66,66,88,-89,90,-68,-62,-21,2,37,-15,-13,-24,-23,3,-58,-9,-71,0,37,-28,22,52,-34,24,-8,-20,29,-98,55,4,36,-3,-9,98,-26,17,82,23,56,54,53,51,-50,0,-15,-50,84,-90,90,72,-46,-96,-56,-76,-32,-8,-69,-32,-41,-56,69,-40,-25,-44,49,-62,36,-55,41,36,-60,90,37,13,87,66,-40,40,-35,-11,31,-45,-62,92,96,8,-4,-50,87,-17,-64,95,-89,68,-51,-40,-85,15,50,-15,0,-67,-55,45,11,-80,-45,-10,-8,90,-23,-41,80,19,29,7 };
	Bubble_Sort(arr, sizeof(arr) / sizeof(int));
	show(arr, sizeof(arr) / sizeof(int));
	return 0;
}

1.5.1 注:

该数组是我在刷力扣时老通不过的一组例子,所以我现在写的所有有关排序的例子都用它来测试!!

2.选择排序

2.1选择排序的思想

选择排序也叫简单选择排序,在每一趟排序时,找到最小值,将其与第一个值进行交换,冒泡排序是每一趟结束后能找到最大值,两种算法有相似性
排序算法——冒泡排序和选择排序_第4张图片

2.2选择排序的性能分析

  • 选择排序:时间复杂度O(n^2) 空间复杂度O(1)
  • 稳定性:不稳定
    排序算法——冒泡排序和选择排序_第5张图片

2.3选择排序源代码

//选择排序  时间复杂度O(n^2) 空间复杂度O(1)   稳定性:不稳定
void Select_Sort(int *arr, int len)
{
	for(int i=0; i<len-1; i++)//控制循环的趟数   len-1趟
	{
		int min = i;//让min 保存 这一趟循环中"待排序序列"的第一个值的下标
		for(int j=i+1; j<len; j++)//找到这一趟排序中,待排序序列的最小值的下标,用min保存
		{
			if(arr[j] < arr[min])//如果发现了比min指向的值还要小的值,则min修改指向
			{
				min = j;
			}
		}
		//此时,里面这一层for循环跑完,代表着min正保存着待排序序列的最小值的下标
		// 而此时待排序序列的第一个值的下标,由变量i保存

		if(min != i)//如果min==i, 代表着待排序序列最小值就是待排序序列第一个值
		{
			int tmp = arr[min];
			arr[min] = arr[i];
			arr[i] = tmp;
		}
	}
}

2.4运行结果

排序算法——冒泡排序和选择排序_第6张图片
由图可知,数据从小到大排列,函数功能实现!

2.5主函数与显示函数

在主函数中调用选择排序函数,其余同上即可!

3.总结

冒泡排序和选择排序是最简单最基础的排序算法,是C语言入门时必须要求要掌握的两种算法,缺点是时间复杂度较高,当数据量较大时建议根据情况选择其他算法。

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