js快速排序算法

算法思路:

1.先从数组中取出一个数作为基准数。

2.分区:比基数大的数全放到它的右边,小于或等于它的数全放到它的左边。

3.再对左右区间重复第二步,直到各区间只有一个数。

快速排序的每一轮处理其实就是将这一轮的基准数归位,直到所有的数都归位为止,排序就结束了。整个算法的处理过程如下:

 

具体实现:

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

1.将数组第一个元素做为基准数,为6

2.确定哨兵

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

3. 开始探测,并分区

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

现在交换哨兵i和哨兵j所指向的元素的值。交换之后的序列如下

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

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

将基准数6和3进行交换。交换之后的序列如下:

到此便完成了第一轮分区。此时以基准数6为分界点,6左边的数都小于等于6,6右边的数都大于等于6。

 

4. 对6两边的数组做递归处理即可。

 

问题:

为什么要哨兵j先出动?

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

 

实现代码:

/**
题目:快速排序算法
思路:两个哨兵,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;
	}
//一轮探查未结束,因为结束时i=j 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);

 

 

 

 

更多算法教程  

posted @ 2018-05-26 22:35  我是格鲁特  阅读(197)  评论(0编辑  收藏  举报