插入排序,选择排序,冒泡排序

1.插入排序

插入排序的基本思路:一串无序的数据,第一个数据本身一定是有序的,直接判断第二个数据,如果第二个数据比第一个数据大,判断第三个,如果小,将第一个数据保存到第二个数据的位置,将第二个位置本来的数据放在第一个位置.

对每一个数据都进行这样的比较就能得到一组有序的数

void InsertSort(int* array,int size)
{
	for (int i = 1; i < size; i++)
	{
		//待排序元素的前一个下标
		int a = i - 1;
		//待排元素的值
		int temp = array[i];
		while (a>=0&&temp < array[a])
		{
			array[a + 1] = array[a];
				a--;
		}
		array[a + 1] = temp;
	}
}

插入排序的应用场景:应用于序列接近有序,且数据量小的时候

如果数据太乱,插入排序也能排,但是效率底

数据量大的情况下,不能使用插入排序,因为插入排序是for循环嵌套,栈容易溢出

稳定性:稳定(因为不存在元素之间交换是隔着元素交换的,即只有相邻元素交换才是稳定的)

时间复杂度O(N^2)

空间复杂度O(1)

2.希尔排序

针对插入排序的局限进行了改进(让数据量变小或者让数据接近有序就可以使用插入排序)

假设将一组数据分三组,分组方法为,元素下标对三求余相等的数据是一组.例如下标是0,3,6的数据在一组,1,4,7下标的数据在一组.

分组之后分别对每一组进行插入排序

void ShellSort(int* array,int size)
{
	int sign = size/3-1;
	while (sign)
	{
		for (int i = sign; i < size; i++)
		{
			int a = i - sign;
			int temp = array[i];
			while (a >= 0 && temp < array[a])
			{
				array[a + sign] = array[a];
				a-=sign;
			}
			array[a + sign] = temp;
		}
		sign--;
	}
}

 sign即是外层循环的此数,也标记第一组的第二个数据4,依次往后是第二组的第二个数据,第三组的第二个数据...往后依次类推

sign的取值有很多种,不用只局限于一种,size/3-1比较常用

里层的两个循环和插入排序的意义是一样的,区别在于,插入排序拍一组数据,希尔排序排多组数据,所以为了定位到本组内的数据需要减去组数找到本组的前一个元素,或者加组数找到本组的后一个元素.

希尔排序不稳定,因为存在跨元素交换或覆盖的情况

注意:希尔排序用于数据量比较大的情况,如果数据量小.不建议用希尔.因为希尔排序要注意分组的个数,因为用sign=size/3-1的方法取sign依赖于size,如果size较小,最外层可能循环次数太少,不足以完成排序,甚至一次也执行不了.

3.选择排序

选择排序是每次将数组遍历一遍,标记最大的数和最后一个数进行交换,则最后一个就已经排好了,下一次循环在数组大小为size-1里找最大的最后一个数进行交换.

void SelectSort1(int* array,int size)
{
	int a = size;
	for (int i = 1; i < a; i++)
	{
		int maxpop = 0;
		for(int j=1;j<size;j++)
		{
			if (array[j] > array[maxpop])
			{
				maxpop = j;
			}
		}
		Swap(&array[maxpop], &array[size-1]);
		size--;
	}
}

对于选择排序的优化,既然内层循环一次可以找到一个最大的,那么同时也可以找到一个最小的,内层循环循环一次就可以排好两个数据:

选择排序的优化

void SelectSort2(int* array, int size)
{
	int begin = 0;
	int end = size - 1;
	while (begin < end)
	{
		int minpop = begin;
		int maxpop = end;
		for (int i = begin+1; i <= end; i++)
		{
			if (array[i] < array[minpop])
			{
				minpop = i;
			}
			if (array[i] > array[maxpop])
			{
				maxpop = i;
			}
		}
		Swap(&array[minpop], &array[begin]);
		if (maxpop == begin)
		{
			maxpop = minpop;
		}
		Swap(&array[maxpop], &array[end]);
		begin++;
		end--;
	}
}

4.冒泡排序(升序)

如果后一个数据小于他之前的数据就交换这两个相邻的数据,一趟循环之后就会得到最后一个数据是最大的,依次再排其他数据

void BollleSort(int* array,int size)
{
	for (int i = 0; i < size - 1; i++)
	{
		int sign = 0;
		for (int j = 0; j < size - i-1; j++)
		{
			if (array[j] > array[j + 1])
			{
				Swap(&array[j], &array[j + 1]);
				sign = 1;
			}
		}
		if (sign == 0)
		{
			return;
		}
	}
}

如果循环没有循环到最后数据已经是有序的了,内层for循环里的if语句一次都没有执行,说明数据已经有序,sign一直是0;直接返回,不进行多余的比较

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值