代码改变世界

js快速排序算法解析

  muamaker  阅读(2017)  评论(0编辑  收藏  举报

数组的快速排序算法,和并归排序步骤基本类似。

都是先拆分,后合并。并归排序是:拆分容易,合并难。 快速排序是:拆分难,合并容易

 

要理解快速排序,首先要理解拆分逻辑

要素:找一个基准点,通过操作使得数列的左边全部都是小于他的数,右边全部都是大于他的数;

1、选中基准点,开始索引 i   ,结束索引  j

2、从数列右边开始往左边找,找到比基准点小的,交换位置 i++

3、从数列左边开始往右边找,找到比基准点大的,交换位置 j--

4、循环执行2、3,直到,i 不是小于 j

 

例如: 有数组  var arr = [30,24,5,58,18,36,12,42,39];

           开始索引  i = 0;  结束索引 j = arr.length-1;    基准点  pivot = arr[i]  即为30

   则有如下代码

      

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var arr = [30,24,5,58,18,36,12,42,39];
        var i = 0, j = arr.length-1,pivot = arr[i];
         
        while(i < j ){  //当最后结束时 i = j
            //从右往左找,找到比基准点小等的就交换,交换后,基准点的索引变为 j
            while(i < j && arr[j] > pivot )
                j--;  //排除已经满足条件的点                       
            if(i < j ){
                swap(i++,j,arr);
            }
             
            //从左往右找,找到比基准点大的就交换,交换后,基准点的索引变为 i
            while(i < j && arr[i] <= pivot)
                i++; //排除已经满足条件的点
            if(i < j ){
                swap(i,j--,arr);
            }
        }
         
        function swap(a,b,arr){
            console.log(a,b,arr[a],arr[b])
            var temp = arr[a];
            arr[a] = arr[b];
            arr[b] = temp;
        }
     
        console.log(i,arr); //基准点i,处理好的arr

  

以上代码就是快速排序的核心,如果将数列,不断以上面方式细分,直到分为单个元素。即最后的结果就是一个有序的数列

 

下面给出完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
var arr = [30,24,5,58,18,36,12,42,39];
 
function Partition(arr,low,high){
    var i = low,j = high,pivot = arr[i];
     
    while(i < j ){
        //从右往左找
        while(i < j && arr[j] > pivot )
            j--;                       
        if(i < j ){
            swap(i++,j,arr);
        }
         
        //从左往右找
        while(i < j && arr[i] <= pivot)
            i++;
        if(i < j ){
            swap(i,j--,arr);
        }
    }
 
    return i;  //返回基准元素位置
}
 
function swap(a,b,arr){
    console.log(a,b,arr[a],arr[b])
    var temp = arr[a];
    arr[a] = arr[b];
    arr[b] = temp;
}
 
function QuickSort(arr,low,high){
    var mid;
    if(low < high){
        mid = Partition(arr,low,high); //返回基准元素位置
        QuickSort(arr,low,mid-1);   //左边快速排序
        QuickSort(arr,mid+1,high);  //右边快速排序
    }
}
QuickSort(arr,0,arr.length-1);
console.log(arr);   

  

 

优化扩展:

   上面的Partition函数中,不管是从右往左,还是从左往右。都是跟pivot基准元素交换。。实际上,可以先直接左边和右边交换,最后再和基准元素交换,减少交换次数。代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var arr = [30,24,5,58,18,36,12,42,39];
        var i = 0, j = arr.length-1,pivot = arr[i];
        var mid;
        while(i < j ){  //当最后结束时 i = j
            //从右往左找
            while(i < j && arr[j] > pivot )
                j--;  //排除已经满足条件的点                       
            //从左往右找
            while(i < j && arr[i] <= pivot)
                i++; //排除已经满足条件的点
             
            //找到两个点,就相互交换
            if(i < j ){
                swap(i++,j--,arr);
            }
        }
         
        //最后将中间点和基准点交换
        if(arr[i] > pivot){
            mid = i-1;
            swap(0,mid,arr);
        }else{
            mid = i;
            swap(0,mid,arr);
        }
         
        function swap(a,b,arr){
            console.log(a,b,arr[a],arr[b])
            var temp = arr[a];
            arr[a] = arr[b];
            arr[b] = temp;
        }
     
        console.log(mid,arr); //基准点mid,处理好的arr

  

 

使用js的数组方法 , unshift 和push

使用unshift 和push实现,将数列的基准元素,左边全部小于他,右边全部大于他

1
2
3
4
5
6
7
8
9
10
11
   var arr = [30,24,5,58,18,36,12,42,39];
var i = 0, pivot = arr[0], arr2 = [pivot];
for(var j = 1; j < arr.length; j++ ){
    if(arr[j] > pivot){
        arr2.push(arr[j]);
    }else{
        arr2.unshift(arr[j]);
        i++;
    }
}
console.log(i,arr2);           

  

使用 unshift和push实现的快速排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var arr = [30,24,5,58,18,36,12,42,39];
 
function Partition(arr,low,high){
    var i = low,pivot = arr[i];
    var arr2 = [pivot];
    for(var j = low+1; j <= high; j++){
        if(arr[j] > pivot){
            arr2.push(arr[j]);
        }else{
            arr2.unshift(arr[j]);
            i++;
        }
    }
    j = 0;
    for(var k = low ; k <= high ; k++){
        arr[k] = arr2[j++];
    }
    return i;  //返回基准元素位置
}
 
function QuickSort(arr,low,high){
    var mid;
    if(low < high){
        mid = Partition(arr,low,high); //返回基准元素位置
        QuickSort(arr,low,mid-1);   //左边快速排序
        QuickSort(arr,mid+1,high);  //右边快速排序
    }
}
QuickSort(arr,0,arr.length-1);
console.log(arr);

  

努力加载评论中...
点击右上角即可分享
微信分享提示