基于冒泡排序对于无序数列的排序以及它的改编版本

  对于输入一个数组,怎么才可以把它重新排序?

我想,这个问题会有很多种解法,这里,我将会介绍两种解法

1)首当其冲的呢,必然就是冒泡排序,作为一个闻名于新手的语言,冒泡排序还是很不错的一个 排序手段,对于刚入门的我们会提供一个很好的思路

第一步就是输入数组的项数,来确定数组的长度,当然,你也可以直接写出确定好的值,不过后面需要再定义一个变量表示这个值,否则更改数组长度时就会很麻烦。

然后就再定义一个变量i,可以用于遍历数组,并输入数组的值

int n,i;
scanf("%d",&n);
int arr[n];
for(i=0;i<n;i++)
{
    scanf("%d",&arr[i]);
}

这样我们就成功得到了一个数组

接下来就是把数组排序,这个也是整个冒泡排序中最核心的部分。那么,怎么排序呢?我们可以用一个循环表示数组的最大值排序,就是把最大值传递到最后一位,那么我们就需要用这个循环进行数的交换,于是我们就可以得到下面的代码:

for (i=0;i<n-1;i++)
	{
		for (j=0;j<n-1-i;j++)
		{
			if (arr[j]>arr[j+1])
			{
				temp=arr[j];
				arr[j]=arr[j+1];
				arr[j+1]=temp;
			}
		}
	}

这里我们进行了两层循环,我们就要再定义一个变量j以免两层循环相互干扰。首先解析最内层的循环,内层循环的里面还嵌套了一个if语句,if语句就是用来判断前一项是否大于后一项,如果小于就不用换位置了,否则就要更换位置。随着一次内层循环的进行,这样右边就会是数组里面最大的,随着内层这个循环的进行,我们最后就可以让最大的一项留在最后。那么一次循环下来,最大的一项就已经留下最右边了,那么我们内层循环就已经进行了一次。

然后外层循环就执行下一次,此时我们发现j<n-1 - i  ;  i 加了1,所以j的最右边的范围就缩小了1,即我们的内层循环就不需要再对数组最右边的那一项进行判断了(因为大项已经是它了,就不用再判断它了),再进行一次内层循环,就是再把剩下的数选出最大的那一项,再把它放到最右边。

长此以往,我们就发现数组从右边开始成型,每进行一次内层循环,我们就可以“选举”出一个最大的,我们需要判断的项数就少了一项。那么什么时候我们就不用再“选举”了呢?每错,就是当我们需要判断的项数还剩一项时。最开始我们一共有n项,我们判断了第1次就还剩n-1项,第二次就还剩n-2项...直到我们还剩1项时,我们就已经判断了n-1次,然后这个时候整个循环就要停止,所以我们外层循环的条件是i =0;i<n-1;————我们很熟悉,当条件为i=0;i<n;的时候,就是标准的遍历数组,我们会进行n次————所以,当条件是i =0;i<n-1;时,我们的外层循环就进行了n-1次,进行n-1次后我们数组就只剩一项,也不需要再判断大小了,所以就可以停止这个循环了

然后我们就成功得到了一个由小到大排好顺序的数组,然后我们就可以用一个简单的遍历把数组输出就好了:

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

这样我们就成功完成了一个数组的排序

——————————————————分割线——————————————————————

2)我们会发现,冒泡排序虽然好,但是它的原理还是很难让人看懂,尤其是初学者,那么我在这里研究了一个数列排序的改良版,以冒泡排序为灵感,进行了一点改编

最开始还是一样的,进行数组长度的定义和数组的输入:

int n;
scanf("%d",&n);
int i;
int arr[n];
for (i=0;i<n;i++)
{
    scanf("%d",&n);
}

接下来就是重要的排序环节了,同样的,我们需要用到两层循环,所以还要定义一个j变量;

这里,我们为了更加抽象的表示两层循环的嵌套以及内层循环的范围缩减,我们定义一个变量range=n;外层还是和冒泡排序一样使用 i 作为一个计算次数的量。然后外层循环之内我们分割为两部分:一个是遍历寻找maxid,就是通过遍历寻找最大的一项的下标,然后在进行换位置把最大的那个和数组最右互换,最后再把内层循环的范围range减少1,使得我们就可以不用再考虑最右边那项,大概就是这样:


	for (i=0;i<n-1;i++)
	{
		for (j=0;j<range;j++)
		{
			if (arr[maxid]<arr[j])//遍历找到最大项数maxid 
			{
				maxid=j;
			}
		}
		//换位置,把最大项换到数组最末尾 
		temp=arr[maxid];
		arr[maxid]=arr[range-1];
		arr[range-1]=temp;
		range--;//范围减少1 
	}

这样我们就把混杂在一起的那些难以理解的几个步骤巧妙的分开了,同时增加了代码的逻辑性;

每次我们进行换位时,我们的需要判断的数组长度就是range,数组这个时候最右边的就是arr[range-1];再用range--让我们的范围减少,就可以一次获得最大一项的放在最右边

然后,还是一样的,我们再用一个数组遍历输出就可以得到排好序的数组了:

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

怎么样?是不是很很简单?快去试试吧!

(******提醒:在上面的代码中我们使用了变长数组的概念,就是用n之类的变量初始化一个数组,然而这个是在C99标准出现之后才有的,有些编译器是不支持这种语法的,比如VS,在使用时会报错,这个时候就要先用定量来定义数组之后再用一个变量来表示它******)

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值