快速排序算法javascript实现

本文基于这里

1、为什么选择快速排序?

相比较传统做法用嵌套循环排序,时间复杂度由O(n^2)变为O(logn),当问题规模n变大的时候,就能体现快速排序算法的效率了。

2、快速排序的数学计算步骤

假设我们对T = [6,1,2,7,9,3,4,5,10,8]数组进行快速排序。

(1)、确定基准数

我们把数组的第一个元素作为基准数。

基准数的作用就是我们一次计算结束后,把小于基准数额元素都放到基准数的左边,大于等于基准数的元素都放到基准数的右边。例如,我们一次计算之后的T是这样的:

T = [3,1,2,5,4 ,6 ,9,7,10,8]

(2)、确定哨兵

用两个变量i和j,分别指向序列最左边和最右边。我们为这两个变量起个好听的名字“哨兵i”和“哨兵j”。刚开始的时候让哨兵i指向序列的最左边,让哨兵j指向序列的最右边。


首先哨兵j开始出动。哨兵j一步一步地向左挪动(即j--),直到找到一个小于6的数停下来。接下来哨兵i再一步一步向右挪动(即i++),直到找到一个数大于6的数停下来。最后哨兵j停在了数字5面前,哨兵i停在了数字7面前。




接下来开始哨兵j继续向左挪动。他发现了4(比基准数6要小,满足要求)之后停了下来。哨兵i也继续向右挪动的,他发现了9(比基准数6要大,满足要求)之后停了下来。此时再次进行交换。




第二次交换结束,“探测”继续。哨兵j继续向左挪动,他发现了3(比基准数6要小,满足要求)之后又停了下来。哨兵i继续向右移动,糟啦!此时哨兵i和哨兵j相遇了,哨兵i和哨兵j都走到3面前。说明此时“探测”结束。我们将基准数6和3进行交换。交换之后的序列如下:





到此第一轮“探测”真正结束。此时以基准数6为分界点,6左边的数都小于等于6,6右边的数都大于等于6。然后对6两边的数组做递归处理即可。

3、深入了解快速排序的几个问题。

(1)、为什么要哨兵j先出动?



举个例子,假设让哨兵i先动,到如上图这一步。哨兵继续往前走,到9的位置,发现i和j相遇,这时候你就要交换9和6的位置,排序就乱了,大于6的数出现在了左边。原因就是哨兵j停留的位置一定比基准数大,如果让i先走,就有可能在哨兵j的位置相遇,这时交换基准数和相遇位置就会出错。

(2)、代码里的边界问题

/**
题目:快速排序算法
思路:两个哨兵,i,j,j从右边找比基数小的,i从左边找比基数大的,然后交换两个目标元素的位置,直到i=j,然后交换i和基数的位置,递归处理。
**/
function quick_sort(arr,from,to){
	var i = from; //哨兵i
	var j = to; //哨兵j
	var key = arr[from]; //标准值
	if(from >= to){ //如果数组只有一个元素
	   return;
	}
	while(i < j){
		while(arr[j] > key && i < j){ //从右边向左找第一个比key小的数,找到或者两个哨兵相碰,跳出循环
			j--;
		}
		while(arr[i] <= key && i < j){  //从左边向右找第一个比key大的数,找到或者两个哨兵相碰,跳出循环,这里的=号保证在本轮循环结束前,key的位置不变,否则的话跳出循环,交换i和from的位置的时候,from位置的上元素有可能不是key
			i++;
		}
		/**
		  代码执行道这里,1、两个哨兵到找到了目标值。2、j哨兵找到了目标值。3、两个哨兵都没找到(key是当前数组最小值)
		**/
		if(i < j){ //交换两个元素的位置
			var temp = arr[i];
			arr[i] = arr[j];
			arr[j] = temp;

		}
	}
	arr[from] = arr[i] //
	arr[i] = key;
    quick_sort(arr,from,i-1);
	quick_sort(arr,i+1,to);
}

var arr = [3,3,-5,6,0,2,-1,-1,3];
console.log(arr);
quick_sort(arr,0,arr.length-1);
console.log(arr);
while(arr[i] <= key && i < j)

这里‘=’号的作用就是为了防止哨兵i第一次移动的时候停留在基准数的位置,然后基准数和哨兵j所在的位置发生交换,倒着基准数位置的元素发生变化。


  • 17
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值