选择排序法和冒泡排序法

选择排序法

思想:从待排序元素中的第一个开始,每一个依次与后面的所有元素作比较,再交换值。

#include <stdio.h>

int main()
{
	int arr[10] = {100,29,40,56,78,34,6,2,97,18};
	int i,j,t;
	for(i=0; i<10; i++)			//从第一个开始
	{
		for(j=i+1; j<10; j++)   //依次与后面的每个元素作比较
		{
			if(arr[i] > arr[j])
			{
				t = arr[i];
				arr[i] = arr[j];
				arr[j] = t;
			}
		}
	}

	for(i=0; i<10; i++)
		printf("arr[%d] = %d\n",i,arr[i]);
		
	return 0;
}

优化:
我们不能减少比较次数,但是可以减少交换次数,比而不换,记录下标,与后面所有元素比较完后,再来交换值。

#include <stdio.h>

int main()
{
	int arr[10] = {100,29,40,56,78,34,6,2,97,18};
	int i,j,t,idx;
	for(i=0; i<10; i++)			//从第一个开始
	{
		idx = i;  //假设当前元素最小
		for(j=i+1; j<10; j++)   //依次与后面的每个元素作比较
		{
			if(arr[idx] > arr[j])
			{
				idx = j; //有比当前元素更小的,更新最小下标,直到循环结束
			}
		}
		if(idx != i)  //idx != i,假设不成立,交换最小下标所在元素和当前元素的值
		{
			t = arr[i];
			arr[i] = arr[idx];
			arr[idx] = t;
		}
	}

	for(i=0; i<10; i++)
		printf("arr[%d] = %d\n",i,arr[i]);
		
	return 0;
}

冒泡排序

思想:每次从头开始,依次比较相邻元素,再交换。经过一轮比较后,就已经确定好最后一个元素的值。再进行下一轮比较,已经排好的最后一个元素就可以不参加排序了。
图示:
在这里插入图片描述
如何确定i,j边界:
N个数,经过一轮比较后,会排好最后一个元素,当只剩两个数未排好时,又经一轮过后,最后一个数排好的同时,第一个数也已经排好,所只需要N-1轮比较就能全部排好。所以外重循环i<N-1(数组元素下标从0开始)。
在一轮比较之中,第一轮需要比较N-1次,每一轮过后,最后一个元素不再参与比较,所以在接下来每一轮中比较次数依次减少一次,所以内重循环比较次数为j < N-1-i;

#include <stdio.h>
#define N 10
int main()
{
	int arr[N] = {100,29,40,56,78,34,6,2,97,18};
	int i,j,t;
	for(i=0; i<N-1; i++)
	{
		for(j=0; j<N-1-i; j++)
		{
			if(arr[j] > arr[j+1])
			{
				t = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = t;
			}
		}
	}
	for(i=0; i<N; i++)
		printf("%d\n",arr[i]);

	return 0;
}

优化:
当出现在比完一轮或两轮,这组数据已经变得有序了,后面的每轮比较都不会再交换值了,也就没有意义了,我们就可以提前结束循环。

#include <stdio.h>
#define N 10
int main()
{
	int arr[N] = {100,29,40,56,78,34,6,2,97,18};
	int i,j,t;
	int flag = 1;      //定义一个标志
	for(i=0; i<N-1; i++)
	{
		flag = 1;
		for(j=0; j<N-1-i; j++)
		{
			if(arr[j] > arr[j+1])
			{
				flag = 0;   //进入交换,意味着这一轮比较是必要的,则把标记位置为0;
				t = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = t;
			}
		}
		if(flag)
			break;   //若flog为1,则意味着这一轮比较没有再交换值,说明已经有序,提前结束循环。
	}
	for(i=0; i<N; i++)
		printf("%d\n",arr[i]);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值