it. java 冒泡排序 求详细解说 此图为例,循环顺序等等!
发布网友
发布时间:2022-04-24 11:18
我来回答
共3个回答
热心网友
时间:2022-05-22 02:46
//定义一个int类型数组
int[] a = {3,5,6,7,11,1};
//定义一个临时变量,此变量是用于存储要进行交换的数据的
int temp = 0;
//这里首先要说明冒泡排序的思想.你可以这样理解,当我们看到一组数的时候想要排序
//是很困难的,但是我们能做的是在这组数中一眼看出哪个数最大或者哪个数最小,那
//么我们可以把这个最大或者最小的数记下来并把它放到数列的最右边,这样我们就通
//过让这个最大或最小的数"冒泡"来将它排除除去,后面只需要在剩余的数中重复寻找
//最大或者最小的数这个操作,我们就可以将一组数进行排序了.我们的大脑在进行寻
//找最大或者最小的数的时候往往都是先记住一个数,然后再进行比较,当找到一个更
//大或者更小的数的时候记住新的那个数,这样不断的重复下去最后记住的一定是最大
//或者最小的那个数.冒泡排序正是模拟了我们寻找最大或者最小数的这种思维并把它
//实现.
//那么之前明白了思想,接下来解析代码.首先我们在排序的时候分为两步,第一步是依
//次比较寻找最大或者最小的数,第二步是重复寻找最大或者最小数的过程,所以我们
//在写代码的时候会有两个循环.
//外层循环,这个循环的意义就是告诉程序我们一共要重复多少次寻找最大数或者最小
//数的过程.其中i并不代表数组下标而是我们的循环次数,因为我们一共要重复跟数组
//数字个数相同的次数,所以一般直接写i=0;i<a.length.这样循环会执行的次数与数
//组数字个数正好相同.当然这里可以有提升效率的方式,也就是i<a.length-1,因为我
//们不需要执行数组数字个数的次数,少一次正好,最后当其它的数字都排好之后剩下
//的那个不需要再去寻找最大或者最小的数了,因为它已经是最大或者最小的数了.
for(int i=0;i<a.length;i++){
//内层循环,这里所做的操作就是我们寻找最大或者最小数的过程,这里的j代表的就是
//数组的下标了,也就是数组中的哪个数字.我们每一次都需要从第一个数开始一直到
//最后一个数才能确定哪个数字是最大或者最小的.就相当于我们的肉眼从第一个数看
//到最后一个数一样.这里也有提升效率的方式,也就是j<a.length-1-i,之前的-1是因
//为我们在进行两两比较的时候都是拿当前下标的数去跟下一个下标的数进行比较,当
//你执行到倒数第二个数的时候其实已经在拿倒数第二个数跟倒数第一个数进行比较了
//,此时其实已经将整个数组比较完了,如果再执行到倒数第一个数你就没有下一个数可
//以比较了,这是逻辑错误,在代码中也会报出ArrayIndexOutOfBounds也就是数组越界
//的错误,所以这个-1跟外层循环的-1提高效率不同,这里是必须有的.再说后面提高效
//率的-i,因为我们每一次都会将一个最大或者最小的数找出来放到最后,那么以后我
//们就无需再去关注它了,所以我们寻找的范围并不需要是整个数组而是每次找完之后
//剩余的数组,i的值一开始为0,随着不断地找每次都会+1,也就是说我们在第一次寻找
//的时候忽略0个数,以后忽略1,2,3...直到最后寻找的范围只有3个,2个,1个(当然了
//如果外层循环没有加-1的话实际上还会寻找0个,循环会变成j=0;j<0,这样明显是没
//有意义的,所以外层循环的-1在这里还会影响,不仅是外层少循环一次那么简单)
for(int j=0;j<a.length-1;j++){
//了解了冒泡的思想以及两个循环代表的意义,那么这里就来做我们记忆最大或者最小
//数的操作.主要思想就是当我们找到一个数的时候去跟下一个数进行比较,下面以从
//小到大为例来讲解.首先我们比较当前的这个数a[j]与下一个数a[j+1],因为从小到
//大排列所以我们需要找最大的数,那么我们来判断当前的这个数是否比下个数大,如
//果小的话我们就舍弃当前数不做操作,如果大的话我们当然要把当前的这个数带走
//继续跟后面的数判断,我们带走的方式便是交换两个数,这样我们下次循环的时候下
//标到了j+1的位置,此时的数正是我们刚刚比较出来并交换到这里的较大的数.这样将
//整个数组遍历一遍之后我们肯定会找到这组数中最大的那个.
//这里判断当前数是否比下一个数要大(同理如果要从大到小排列只需要把大于号换成
//小于号即可,就是每次判断当前数是否比下一个数要小)
if(a[j]>a[j+1]){
//到了这里证明当前数大于下一个数,那么要将两个数进行交换我们需要第三方空间的
//辅助.此时我们定义的变量temp就派上用场了.不过这里你的temp是定义在循环之外
//的,但是结果不影响.比较好的写法应该是循环外不去定义而是在这里定义临时变量,
//因为这个变量我们只在这里用到,每次交换完就让它消亡就好了,不需要多占用内存
//空间,较好的写法是int temp = a[j+1];
temp=a[j+1];
//经过上一步之后我们有3个值分别是a[j],a[j+1],temp.此时a[j+1]与temp的值是相
//同的都是a[j+1]的值,然后我们再将a[j]的值交给a[j+1],这时3个值中a[j]与a[j+1]
//的值是相同的都是a[j],另外一个temp的值是a[j+1]的值
a[j+1]=a[j];
//最后只要把temp的值交给a[j]就完成了我们的交换了.这里你要想一个三角形的图.
//我比较懒就不画图了,粗略用文字排版给你解释一下.
// temp
// temp最后把值给a[j] a[j+1]先把值给temp
// a[j] a[j]再把值给a[j+1] a[j+1]
//如上图所示这是个循环的,当然第一步一定要先把a[j+1]的值交给temp而不能直接把
//a[j]的值给a[j+1],那样就会直接丢失a[j+1]的值了.以上的循环也可以反过来也就
//是a[j]把值给temp然后a[j+1]把值给a[j]最后temp把值给a[j+1]
a[j]=temp;
}
}
}
//打印排序之后的数组,我就不多解释了
for(int i=0;i<a.length;i++){
System.out.println(a[i]);
}
//最后附送给你优化之后的代码以及执行每一步之后结果的分析
int[] a = {3,5,6,7,11,1};
for(int i=0;i<a.length-1;i++){
for(int j=0;j<a.length-1-i;j++){
//从大到小
if(a[j]<a[j+1]){
int temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
//再附送你一个提高效率的交换方式,但是只适用于整型数据.这是利用按位
//异或也就是^的特性来交换两个数,不会使用第三方空间.具体原理想知道私信我,否
//则又要很麻烦的的解释TAT
//if(a[j]<a[j+1]){
// a[j] = a[j]^a[j+1];
// a[j+1] = a[j]^a[j+1];
// a[j] = a[j]^a[j+1];
//}
}
}
//以上代码每一次外层循环执行之后的结果
//原始数组 3,5,6,7,11,1
//第一次拿着3开始比较,所以将5 6 7 11都换到前面去了,到最后一个1的时候没有换
//因为1小于3
//5 6 7 11 3 1
//第二次拿着5开始比较把6 7 11都换到前面了,遇到3的时候发现3更小,本应该拿着3
//再去比较1的,但是由于之前已经找出了最小的1,所以执行的时候-i也就是-1,虽然看
//不出来,但是程序执行的时候实际上没有拿着3去跟1比了,执行5跟3比较就已经结束了
//6 7 11 5 3 1
//第三次拿着6开始比较把7跟11都换了,然后比较到5就结束了
//7 11 6 5 3 1
//第四次用7开始比较把11换了,比较到6就结束了
//11 7 6 5 3 1
//最后一次只拿着11跟7比较了一次就结束了,如果外层循环没有-1实际上还会输出一
//次这个结果,也就是用11谁都不去比较的一次没用的循环
//11 7 6 5 3 1
//以上,纯粹手打,纯粹无聊,只为解惑.
//最后容许我吐槽一下这排版真是困难Σ( ° △ °|||)︴
热心网友
时间:2022-05-22 04:04
第一次进入外层循环,i=0时,继续第一次进入内层循环,j=0。
如果a[0]>a[1],则把a[1]的值赋给temp临时变量,再与a[0]交换值,其实这几句代码的功能就是换位置,也就是“冒泡”,这样就会把a[0]与a[1]中比较小的值给排到前面去。
内层循环第一次执行完毕后,继续执行第二次内层循环,再把a[1]与a[2]中比较小的值排到前面去,这样一来,当内层循环全部执行一次后,就会初步的把大小排列了一次,但还不是最终结果。
当第一次的内层循环执行完毕后,就开始执行第二次外层循环,接下来也就会再次循环一轮内层循环,进一步的排序,当外层循环全部执行完毕后,循环结束,数组排序完毕,如图的冒泡排序,得到的是一个从小到大排列的数组。追问谢谢!
热心网友
时间:2022-05-22 05:39
外循环,枚举每一个元素、内循环从下一个开始找,和前一个元素比较,如果大于(小于),则进行交换。。。。。。。。。。。。。。