目录
任务描述
相关知识
冒泡排序
一趟冒泡排序
冒泡排序全过程
选择排序
一趟选择排序
选择排序全过程
编程要求
任务描述
本关任务:掌握冒泡排序和选择排序。
相关知识
所谓排序是指将一组数据按照从小到大(或从大到小)的顺序重新排列,排序是面试常考的问题之一。
排序一般分为两个步骤:比较和移动。比较指判断两个数据之间的大小关系,移动指根据大小关系把数据移动到合适的位置上。
待排序的数据大多是放置在数组中,一是因为数组中的数据有相对的顺序,二是遍历数组操作起来比较简单。
下面介绍 JavaScript 中两种常见的排序方式:冒泡排序和选择排序。
冒泡排序
一趟冒泡排序
先介绍一趟冒泡排序的过程。
以升序为例,从第一个元素开始,将第一个元素与第二个元素比较,如果第一个元素大于第二个元素,交换这两者。
如图1所示,9比5大,交换两者的位置后,9就到后面去了。
图1
然后第二个元素与第三个元素比较,将大的移动到后面;第三个元素与第四个元素比较......,这样一直进行下去,直到倒数第二个元素和最后一个元素进行比较,称为一趟冒泡排序,结束后最大的元素已经移到了索引最大处。图2展示了每一次比较并交换后的数组:
图2
可以看到,一趟冒泡排序结束后,最大的元素`9`移到了索引最大处。
冒泡排序全过程
接下来对除了最后一个元素的数组进行第二趟冒泡排序,结果是第二大的元素到了索引第二大的地方。这样一直进行下去,直到整个数组有序或者某一趟排序的时候不存在元素的交换。如图3
图3
第四趟冒泡过程中,未发生元素的交换,结束。
因为排序的原理是不断的把大的数据往上浮动,故而命名为冒泡排序。
// 冒牌排序
var arr = [9,5,8,0,2,6];
var aLength = arr.length;
var temp;
var flag = 0; // 元素交换的标志位
for(var i = 1;i < aLength;i++) { // 共进行n-1次冒泡
flag = 0;
for(var j = 0;j < aLength-i;j++) { // 一次冒泡
if(arr[j]>arr[j+1]) { // 交换元素
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
flag = 1;
}
}
if(flag == 0) break; // 本次冒泡没有元素交换
}
console.log(arr);
冒泡排序关键在于这两个循环的控制,外层循环控制冒泡的次数,一般是n-1
次,n
表示数组长度。
内循环j
的初值为0
,因为不论是第几趟冒泡,都是从arr[0]
开始遍历数组,j
的上限设置为arr.length-i
,因为随着冒泡的进行,越往后需要比较的数组的索引上限越小。
选择排序
一趟选择排序
原理:遍历数组,记录下最大元素的索引值,将最大的元素与数组最后一个元素交换,这样最大的元素到了索引值最大的地方,称为一趟选择排序。与冒泡不同的是,只会发生一次交换。如图4
图4
可以看到9移到了索引最大处。
选择排序全过程
第二趟选择排序是在除了最后一个元素的数组中选择最大的元素,将它与索引值第二大的元素交换,结束后第二大的元素也到了最终的位置上。这样一直进行下去,一共n-1
趟选择排序。如图5
图5
// 选择排序
var arr = [6,12,3,34,1,56,77,0,2,43];
var aLength = arr.length;
var temp;
var max = arr[0];
var maxIndex = 0;
for(var i = 0;i < aLength-1;i++) { // 共进行n-1次选择
for(var j = 1;j < aLength-i;j++) { // 一次选择
if(arr[j] > max) {
max = arr[j];
maxIndex = j;
}
}
// 将本次选出的最大元素移动到最终的位置上
temp = arr[aLength-i-1];
arr[aLength-i-1] = arr[maxIndex];
arr[maxIndex] = temp;
var max = arr[0];
var maxIndex = 0;
}
console.log(arr);
这里也有两个大循环,第一个循环控制总的排序趟数,第二个循环求本次选择出的最大元素的索引值,第二个循环结束后将本次的最大值与最终位置上的元素交换。
编程要求
本关的编程任务是补全右侧代码片段中 Begin 至 End 中间的代码,具体要求如下:
-
函数
mainJs(a)
中的变量arr
是一个数组,你需要对该数组进行选择排序; -
返回选择排序进行过程中,在每一趟交换前,待排序子数组的最大元素的位置组成的数组;
-
比如对于上面相关知识中的数组
[9,5,8,0,2,6]
,第一次交换前,最大的元素9的索引是0,第二次交换前,最大元素8的索引是2,第三次交换前最大元素6的索引是0,第四次交换前最大元素5的索引是1,第五次交换前最大元素2的索引是1,第六次交换前最大元素0的索引是0。索引需要返回的数组是[0,2,0,1,1,0]
;function mainJs(a) { var arr = a.split(","); for(var i = 0;i < arr.length;i++) { arr[i] = parseInt(arr[i]); } //请在此处编写代码 /*********begin*********/ var length = arr.length; var max = arr[0]; var t = 0; var maxindex = 0; var newArr = new Array(); for (var i = 0; i < length - 1; i++){ for (var j = 1; j < length - i; j++){ if (arr[j] > max) { max = arr[j]; maxindex = j; } } newArr.push(maxindex); t = arr[length - i - 1]; arr[length - i - 1] = arr[maxindex]; arr[maxindex] = t; var max = arr[0]; var maxindex = 0; } return newArr; /*********end*********/ }