冒泡 / 选择 / 插入排序

冒泡 / 选择 / 插入排序

小编学习数据结构也有一阵子了,对于萌新而言最重要的两种算法便是排序与查找,小编结合自己所学经历来给大家分享一下,希望能对你有所帮助

???排序

在讲经典的简单排序之前,小编想分享一下初学者们经常会写的一种排序

int main()
{
	char arr[5] = {5,2,3,1,4};
	for(int i=0; i<5; ++i)
	{
		for(int j=i+1; j<5; ++j)
		{
			int temp = 0;
			if(arr[j]<arr[i])
			{	
				temp = arr[i];
				arr[i] = arr[j];
				arr[j] = temp;
			}
		}
	}
}

在这里插入图片描述
这种写法看似与简单的排序算法有点相像,但是其实有着本质上的区别,上面的例子中第一次排序得到的结果是 1 5 3 2 4,其中第二小的数字2反而从原先的第二位被换到了倒数第二位,直到i = 5时才结束循环获得排序后的最终结果。可见这样的排序并不高效!

冒泡排序

冒泡排序是一种交换排序,它的基本思想是:两两比较相邻的关键字,若它们反序则交换

#define swap(a,b) {typeof(a) t=a;a=b;b=a;}

void bubble_sort(int *arr ,size_t len)
{
	for(int i = len-1; i>0; --i)
	{
		bool flag = true;
		for(int j = 0; j<i; j++)
		{
			if(arr[j]>arr[j+1])
			{
				swap(arr[j],arr[j+1]);
				flag = false;
			}
		}
		if(flag) break;
	}
}

举数组arr[5] = {5,1,2,3,4}为例
在这里插入图片描述
冒泡排序经过一次循环便得到了排序的结果,并通过标志位flag直接跳出循环,而且不难发现在冒泡排序的过程中每次都在将小数上移,大数后移。面对部分有序的情况下,冒泡排序可以敏锐的察觉到它的有序性,且在得到最终结果后也能能过标志位flag及时避免不必要的比较

选择排序

选择排序在我心中其实是对???排序的一种升级,在???排序中,数字在一趟内层循环中可能会不停的发生交换,那我们能不能让它做一个能够抓住机会的数组,在找到合适的位置时才让数据发生交换?这就是选择排序的思想

#define swap(a,b) {typeof(a) t=a;a=b;b=t;}

void select_sort(int *arr, size_t len)
{
	for(int i=len-1; i>0; --i)
	{
		int max = i;
		for(int j=0; j<i; ++j)
		{
			if(arr[j]>arr[max])
				max = j;
		}
		if(i!=max)
			swap(arr[max],arr[i]);
	}
}

举数组arr[5] = {2,3,4,5,1}为例
在这里插入图片描述
选择排序的比较次数与???排序是一样的,但是每次在比较完后不急着交换数据,正所谓放长线钓大鱼,选择排序等到确认了最后的目标时才进行数据交换

插入排序

插入排序的原理是将一个关键字插入到已经排序好的表中,构成新的有序表。插入排序在依次找到合适的位置时并不急着进行交换,而是选择与选择排序相同的方式记录下标

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

#define swap(a,b) {typeof(a) t=a;a=b;b=t;}

void insert_sort(int *arr, size_t len)
{
	for(int i=1; i<len-1; ++i)
	{
		int t = arr[i],k=i;//k用来记录位置
		for(int j=i-1; j>=0 && arr[j]>t; j--)
		{
			arr[j+1] = arr[j];
			k=j;
		}
		arr[k] = t;
	}
}

举数组arr[5] = {1,5,2,3,4}为例
在这里插入图片描述
插入排序在在序列本身就大致有序的时候非常简单,并且结合了选择排序的思想使得交换的次数也得到了优化

总结

三种简单的排序算法在函数的样子上十分相似,小编认为重要的是三种排序算法的循环条件,小编在写冒泡排序与选择排序时,外层循环均由数组的最后一位开始,目的是为了让每一次外层循环获得数组中的最大值并放到最后。小编将在后续继续分享更好的排序算法:堆排序、归并排序、快速排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值