一、题干:
请填充代码,使mySort()能使传入的参数按照从小到大的顺序显示出来。
function mySort() {
var tags = new Array();//使用数组作为参数存储容器
请补充你的代码
return tags;//返回已经排序的数组
}
var result = mySort(50,11,16,32,24,99,57,100);/传入参数个数不确定
console.log(result2);
二、说明
1、简介
排序算法是用来根据元素对应的比较运算符重新排列给定的数组的算法,输出的数组是一个根据比较符从小到大或者从大到小依次排列的数组。比较运算符是用于确定相应数据结构中元素的新顺序,比如在整数数组里面,对应的比较符号就是大于或者小于号,用户也可以自己定义对应的比较运算符。
比如如果输入是[4,2,3,1],按照从小到大输出,结果应该是[1,2,3,4]
2、特性
稳定性
如果在数组中有两个元素是相等的,在经过某个排序算法之后,原来在前面的的那个元素仍然在另一个元素的前面,那么我们就说这个排序算法是稳定的。
如果在排序之后,原来的两个相等元素中在前面的一个元素被移到了后面,那么这个算法就是不稳定的。
比如排序之前数组为[3(a),2,3(b)](其中a和b分别代表两个不同的3),经过某个排序算法之后是[2,3(a),3(b)],那么这个算法就是稳定的;如果变成了[2,3(b),3(a)],那么这个算法是不稳定的。
三、解法:
基本算法
首先定义基本的交换数组元素的基本方法,节省后面的代码量。
function swap(nums, i, j){
var temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
1、sort()
function mySort(){
var tags = new Array(); //使用数组作为参数存储容器
tags = [...arguments];
// for(let i = 0;i < arguments.length; i ++){
// tags.push(arguments[i]);
// }
tags.sort((a,b) => {
return a - b
})
return tags;
}
var result = mySort(50,11,16,32,24,99,57,100); //传入参数个数不确定
console.info(result);
2、冒泡排序
冒泡排序是从左到右依次比较相邻的两个元素,如果前一个元素比较大,就把前一个元素和后一个交换位置,遍历数组之后保证最后一个元素相对于前面的永远是最大的。然后让最后一个保持不变,重新遍历前n-1个元素,保证第n-1个元素在前n-1个元素里面是最大的。依此规律直到第2个元素是前2个元素里面最大的,排序就结束了。
因为这个排序的过程很像冒泡泡,找到最大的元素不停的移动到最后端,所以这个排序算法就叫冒泡排序。
function mySort2(){
var tags = new Array(); //使用数组作为参数存储容器
tags = [...arguments];
for(var i = arguments.length - 1; i >= 1; i--){
for(var j = 1; j <= i; j++){
if(tags[j-1] > tags[j]){
swap(tags,j-1,j);
}
}
}
return tags;
}
var result2 = mySort2(50,11,16,32,24,99,57,100); //传入参数个数不确定
console.info(result2);
3、快速排序
其核心的思路是取第一个元素(或者最后一个元素)作为分界点,把整个数组分成左右两侧,左边的元素小于或者等于分界点元素,而右边的元素大于分界点元素,然后把分界点移到中间位置,对左右子数组分别进行递归,最后就能得到一个排序完成的数组。当子数组只有一个或者没有元素的时候就结束这个递归过程。
function mySort3(){
var tags = new Array(); //使用数组作为参数存储容器
tags = [...arguments];
quickSort(tags,0,tags.length - 1);
return tags;
}
function quickSort(nums, left, right){
if(left >= right){
return nums;
}
var low = left + 1;
var high = right;
while(low <= high){
if(nums[low] > nums[left]){
swap(nums,low,high);
high--;
}else{
low++;
}
}
low--;
swap(nums,low,left);
quickSort(nums,left,low - 1);
quickSort(nums,low + 1, right);
return nums;
}
var result3 = mySort3(50,11,16,32,24,99,57,100); //传入参数个数不确定
console.info(result3);
方法二:
var quickSort2 = function(arr){
if(arr.length <= 1){return arr};
var pivotIndex = Math.floor(arr.length / 2);
var pivot = arr.splice(pivotIndex,1)[0];
var left = [];
var right = [];
for(var i = 0; i < arr.length; i++){
if(arr[i]< pivot){
left.push(arr[i]);
}else{
right.push(arr[i]);
}
return quickSort2(left).concat([pivot],quickSort2(right));
}
4、选择排序(选最)
选择排序的思路比较简单,先找到前n个元素中最大的值,然后和最后一个元素交换,这样保证最后一个元素一定是最大的,然后找到前n-1个元素中的最大值,和第n-1个元素进行交换,然后找到前n-2个元素中最大值,和第n-2个元素交换,依次类推到第2个元素,这样就得到了最后的排序数组。
其实整个过程和冒泡排序差不多,都是要找到最大的元素放到最后,不同点是冒泡排序是不停的交换元素,而选择排序只需要在每一轮交换一次。
function mySort4(){
var tags = new Array(); //使用数组作为参数存储容器
tags = [...arguments];
for(var i = tags.length - 1; i >= 1; i --){
var max = 0;
for(var j = 0; j <= i; j++){
if(tags[max] < tags[j]){
max = j;
}
}
swap(tags,max,i);
}
return tags;
}
var result4 = mySort4(50,11,16,32,24,99,57,100); //传入参数个数不确定
console.info(result4);
方法二:
var selectSort2 = function(arr){
for(var i = 0; i < arr.length - 1; i ++){
var min = i;
for(var j = i; j < arr.length; j ++){
if(arr[min] > arr[j]){
min = j;
}
}
swap(arr, i, min);
}
return arr;
}
5、插入排序(起扑克牌)
插入排序的核心思想是遍历整个数组,保持当前元素左侧始终是排序后的数组,然后将当前元素插入到前面排序完成的数组的对应的位置,使其保持排序状态。有点动态规划的感觉,类似于先把前i-1个元素排序完成,再插入第i个元素,构成i个元素的有序数组。
function mySort5(){
var tags = new Array(); //使用数组作为参数存储容器
tags = [...arguments];
for(var i = 1; i < arguments.length; i++){
var j = i;
while(j > 0 && tags[j] < tags[j - 1]){
swap(tags,j,j-1);
j--;
}
}
return tags;
}
var result5 = mySort5(50,11,16,32,24,99,57,100); //传入参数个数不确定
console.info(result5);
6、归并排序
归并排序是典型的使用分治思想(divide-and-conquer)解决问题的案例。在排序的过程中,把原来的数组变成左右两个数组,然后分别进行排序,当左右的子数组排序完毕之后,再合并这两个子数组形成一个新的排序数组。整个过程递归进行,当只剩下一个元素或者没有元素的时候就直接返回。
function mySort6(){
var tags = new Array(); //使用数组作为参数存储容器
tags = [...arguments];
mergeSort(tags,0,tags.length - 1);
return tags;
}
function mergeSort(nums, l, r){
if(l >= r){
return;
}
var mid = Math.floor((l + r)/2);
mergeSort(nums,l,mid);
mergeSort(nums,mid+1,r);
var i = l,j = mid + 1;
var n = 0;
var temp = new Array(nums.length);
while(i <= mid && j <= r){
if(nums[i] <= nums[j]){
temp[n++] = nums[i++];
}else{
temp[n++] = nums[j++];
}
}
while(i <= mid){
temp[n++] = nums[i++];
}
while(j <= r){
temp[n++] = nums[j++];
}
for(var k = 0; k < r - l + 1; k++){
nums[l + k] = temp[k];
}
// 以下代码会使浏览器崩溃
// for(var k = 0; k < nums.length; k++){
// nums[l + k] = temp[k];
// }
}
var result6 = mySort6(50,11,16,32,24,99,57,100); //传入参数个数不确定
console.log(result6);
方法二:
var mergeSort = function(arr){
var len = arr.length;
if(len < 2){
return arr;
}
var middle = Math.floor(len / 2);
var left = arr.slice(0,middle);
var right = arr.slice(middle);
return merge(mergeSort(left),mergeSort(right));
}
function merge(left,right){
var result = [];
while(left.length && right.length){
if(left[0] > right[0]){
result.push(right.shift());
}else{
result.push(left.shift())
}
}
while(left.length){
result.push(left.shift());
}
while(right.length){
result.push(right.shift());
}
return result;
}
var result6 = mergeSort([50,11,16,32,24,99,57,100]);
console.log(result6);