排序--插入排序-快速排序(迭代)

74 阅读2分钟


function insertSort(arr, sortByFn) {
	for (let i = 1; i < arr.length; i++) {
		//当前要处理的数
		let temp1=arr[i];
		let temp = sortByFn(arr, i);
		let j = i - 1;
		while (j >= 0 && sortByFn(arr, j) > temp) {
			//如果前一个数大于后一个数,将前一个数往后移一位
			arr[j + 1] = arr[j];
			j--;
		}
		//此时的j是要处理的数排序后应该在的位置
		arr[j + 1] = temp1;
	}
	return arr;
}

function quickSort(arr, left, right, defaultSortByFn) {
	let stack = [[left, right]]; //js中用数组模拟栈
	while (stack.length > 0) {
		//栈不为空时,说明还有序列没有排序好
		const now = stack.pop();
		let right = now[1]; //后进先出,栈顶元素出栈,是为待排序列的最右下标(指针)
		let left = now[0]; //栈顶元素出栈,是为待排序列的最左下标(指针)
		let index = partition(arr, left, right, defaultSortByFn); //划分,将待排序列进行一趟快速排序,最终有一个数获得最终位置,其下标为index
		if (left < index - 1) {
			//将index将待排序列分为两部分
			stack.push([left, index - 1]); //左边那部分左指针入栈
		}
		if (right > index + 1) {
			//右边部分入栈
			stack.push([index + 1, right]);
		}
	}

	return arr; //返回数组
}

// quickSort的一次排序
function partition(arr, left, right, sortByFn) {
	let base1=arr[left];
	let base = sortByFn(arr, left); //基准值,数组中的第一个数,也可以选择最后一个数,中间的也行。可以优化(第一个,中间,最后一个中中间的那个数)
	while (left < right) {
		//循环跳出条件,注意不能等于

		while (left < right && base <= sortByFn(arr, right)) {
			//从后往前找第一个比基准值小(相等也行)的元素
			right--;
		}
		arr[left] = arr[right]; //比基准值小的元素移动到左端
		while (left < right && base >= sortByFn(arr, left)) {
			//从前往后找第一个比基准值大的元素   将记住这里的base有等于号
			left++;
		}
		arr[right] = arr[left]; //比基准值大的元素移动到右端
	} // 跳出循环时left和right相等,此时的left和right就是base的正确索引位置

	arr[left] = base1; //最终left=right,基准元素的最终存放位置

	return left; //返回基准元素的最终存放位置
}

//sortByFn 比较函数   当不传的时候 默认按数组值升序 当传的时候 按照sortByFn函数计算的数值升序 当需要降序的时候 请改造sortByFn 计算结果取反

const defaultSortByFn = function(arr, index) {
	return arr[index];
};
function sortBy(arr, sortByFn = defaultSortByFn) {
	let len;
	let result;
	if (!(Array.isArray(arr) && ((len = arr.length), len) > 1)) return arr;
	if (len <= 100) {
		console.time("插入排序");
		result = insertSort(arr, sortByFn);
		console.timeEnd("插入排序");
	} else {
		console.time("快速排序");
		result = quickSort(arr, 0, len - 1, sortByFn);
		console.timeEnd("快速排序");
	}
	return result;
}