js(102)~[912] 排序数组-冒泡-选择-归并

177 阅读3分钟

冒泡排序

首先来个概念

冒泡排序的英文Bubble Sort,是一种最基础的交换排序。之所以叫做冒泡排序,因为每一个元素都可以像小气泡一样,根据自身大小一点一点向数组的一侧移动。
冒泡排序的原理: 每一趟只能确定将一个数归位。即第一趟只能确定将末位上的数归位,第二趟只能将倒数第 2 位上的数归位,依次类推下去。如果有 n 个数进行排序,只需将 n-1 个数归位,也就是要进行 n-1 趟操作。 而 “每一趟 ” 都需要从第一位开始进行相邻的两个数的比较,将较大的数放后面,比较完毕之后向后挪一位继续比较下面两个相邻的两个数大小关系,重复此步骤,直到最后一个还没归位的数。

!!! 目前在力扣这个排序数组这道题目中提交可以执行成功,但是提交不了,超出时间限制,之前我3月份都可以提交成功,同样的代码,这里近做学习!

1.1 简单版本

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortArray = function (nums) {
	/* 
	冒泡排序只会操作相邻的两个数据。
	每次冒泡操作都会对相邻的两个元素进行比较,看是否满足大小关系要求。如果不满足就让它俩互换。
一次冒泡会让至少一个元素移动到它应该在的位置,重复 n 次,就完成了 n 个数据的排序工作。 */
	for (let i = 0; i < nums.length - 1; i++) {
		for (let j = 0; j < nums.length - 1-i; j++) {
			if (nums[j] > nums[j + 1]) {
				[nums[j], nums[j + 1]] = [nums[j + 1], nums[j]]
			}
		}
	} 
	
};

1.2 优化版本

比如[1,3.2,4]类似这种的数组,只需要外层循环走一遍就行了,以后都不需要再走了,上面的代码,暴力不管那么多,我就是有多少走多少.所以出现了下面这优化版本,判断一下,排序正确的都不走了!

var sortArray = function (arr) {
        for (let i = 0; i < arr.length - 1 ; i++) {
                let flag = true;
                for (let j = 0; j < arr.length - 1 - i; j++) {
                        if (arr[j] > arr[j + 1]) {
                                [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
                                flag = false;
                        }
                }

                if (flag) {
                        break;
                }
        }
        return arr;
};

选择排序

1 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
2 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
3 重复第二步,直到所有元素均排序完毕。

/* // 方法二 
	*/
	let minIndex = 0;
	for (let i = 0; i < nums.length ; i++) {
		console.log(minIndex, i)
		minIndex = i;
                // 第一次层for循环是nums.length- 1,其实-1也可以去掉
                // 而这这二层for循环得条件 最少是nums.lengt 不能-1 也可以+1 +2
		for (let j = i + 1; j < nums.length; j++) {
			if (nums[j] < nums[minIndex]) {
				minIndex = j;
			}
		};
		console.log(minIndex);
		[nums[i], nums[minIndex]] = [nums[minIndex], nums[i]];

	}

	return nums;

归并排序

步骤如下,简单的说就是把大数组(无序)化成小数组,在小数组拼接成大数组(有序)

1、将给定的列表分为两半(如果列表中的元素数为奇数,则使其大致相等)。
2、以相同的方式继续划分子数组,直到只剩下单个元素数组。
3、从单个元素数组开始,合并子数组,以便对每个合并的子数组进行排序。
4、重复第 3 步单元,直到最后得到一个排好序的数组。

具体代码如下,有两个点需要注意一下
1 到merge里面的两个数组都是有序的,是因为从小数组变大的时候都判断排序了
2 这里就是合并代码的时候merge最后返回数组,用es6写法老是报超时,但是用concat就不会超时



var sortArray = function (nums) {
	if (nums.length < 2) {
		return nums;
	}

	const midI = Math.floor(nums.length / 2);

	const leftArr = nums.splice(0, midI);
	return merge(sortArray(leftArr), sortArray(nums))

};

function merge(ls, rs) {
	let result = [];
	while (ls.length && rs.length) {
		   // 这里需要注意的就是 进到这里面的数组都是有序的
        // 这里就是 哪个小先王数组里面推哪个 记得数字推进新数组老数组的数要去掉
        ls[0] > rs[0] ? result.push(rs.shift()) : result.push(ls.shift())

	}
        // 一种方法
    //  if(ls.length == 0){
    //     result = result.concat(rs);//拼接
    // }
    // if(rs.length == 0){
    //     result = result.concat(ls);
    // }
    // return result;
    
    // 两种方法
    return result.concat(ls, rs)
    // 这个不行老是保超时
	// return [...result, ...ls, ...rs]
}


参考链接 www.php.cn/js-tutorial…