• 快速排序与冒泡排序(面试题)


    今天讲一道前端开发的笔试题,题目如下: 编写快速排序和冒泡排序,并简单对比分析.

    看到题目愣了一下,知道冒泡排序,可什么是快速排序呢?

    下面先来看一下冒泡排序:

    方法一: 每一次对比相邻两个数据的大小,小的排在前面,如果前面的数据比后面的大就交换这两个数的位置

           var arr = [90,0,-10,88,999,100,102,2,3,20];
                function sortArr1(arr){
                    var count = 0;    //统计循环次数
                    for (let i=0;i<arr.length;i++) {
                        //遍历数组,从左往右,相邻两个元素进行比较,把大的数往后面排
                        for (let j=0;j<arr.length-1-i;j++) {
                            if(arr[j]>arr[j+1]){
                                var temp = arr[j+1];    //如果前面的数大于后面的则交换
                                arr[j+1]=arr[j];
                                arr[j]=temp;
    
                            }
                            document.write("第"+(++count)+"次排序后:"+arr);  
                        }
                    }
                    return arr;
                }
                console.log(sortArr1(arr));  //[-10, 0, 2, 3, 20, 88, 90, 100, 102, 999]
                

    方法1执行过程中输出的结果为:

    第1次排序后:0,90,-10,88,999,100,102,2,3,20
    第2次排序后:0,-10,90,88,999,100,102,2,3,20
    第3次排序后:0,-10,88,90,999,100,102,2,3,20
    第4次排序后:0,-10,88,90,999,100,102,2,3,20
    第5次排序后:0,-10,88,90,100,999,102,2,3,20
    第6次排序后:0,-10,88,90,100,102,999,2,3,20
    第7次排序后:0,-10,88,90,100,102,2,999,3,20
    第8次排序后:0,-10,88,90,100,102,2,3,999,20
    第9次排序后:0,-10,88,90,100,102,2,3,20,999
    第10次排序后:-10,0,88,90,100,102,2,3,20,999
    第11次排序后:-10,0,88,90,100,102,2,3,20,999
    第12次排序后:-10,0,88,90,100,102,2,3,20,999
    第13次排序后:-10,0,88,90,100,102,2,3,20,999
    第14次排序后:-10,0,88,90,100,102,2,3,20,999
    第15次排序后:-10,0,88,90,100,2,102,3,20,999
    第16次排序后:-10,0,88,90,100,2,3,102,20,999
    第17次排序后:-10,0,88,90,100,2,3,20,102,999
    第18次排序后:-10,0,88,90,100,2,3,20,102,999
    第19次排序后:-10,0,88,90,100,2,3,20,102,999
    第20次排序后:-10,0,88,90,100,2,3,20,102,999
    第21次排序后:-10,0,88,90,100,2,3,20,102,999
    第22次排序后:-10,0,88,90,2,100,3,20,102,999
    第23次排序后:-10,0,88,90,2,3,100,20,102,999
    第24次排序后:-10,0,88,90,2,3,20,100,102,999
    第25次排序后:-10,0,88,90,2,3,20,100,102,999
    第26次排序后:-10,0,88,90,2,3,20,100,102,999
    第27次排序后:-10,0,88,90,2,3,20,100,102,999
    第28次排序后:-10,0,88,2,90,3,20,100,102,999
    第29次排序后:-10,0,88,2,3,90,20,100,102,999
    第30次排序后:-10,0,88,2,3,20,90,100,102,999
    第31次排序后:-10,0,88,2,3,20,90,100,102,999
    第32次排序后:-10,0,88,2,3,20,90,100,102,999
    第33次排序后:-10,0,2,88,3,20,90,100,102,999
    第34次排序后:-10,0,2,3,88,20,90,100,102,999
    第35次排序后:-10,0,2,3,20,88,90,100,102,999
    第36次排序后:-10,0,2,3,20,88,90,100,102,999
    第37次排序后:-10,0,2,3,20,88,90,100,102,999
    第38次排序后:-10,0,2,3,20,88,90,100,102,999
    第39次排序后:-10,0,2,3,20,88,90,100,102,999
    第40次排序后:-10,0,2,3,20,88,90,100,102,999
    第41次排序后:-10,0,2,3,20,88,90,100,102,999
    第42次排序后:-10,0,2,3,20,88,90,100,102,999
    第43次排序后:-10,0,2,3,20,88,90,100,102,999
    第44次排序后:-10,0,2,3,20,88,90,100,102,999
    第45次排序后:-10,0,2,3,20,88,90,100,102,999

    方法二:

    var times=0;  
                function sortArr2(arr){  
                    for(var i=0;i<arr.length-1;i++){  
                        //遍历数组,获得当前的数arr[i]与它后面的数依次对比
                        for(var j=i+1;j<arr.length;j++){  
                            if(arr[i]>arr[j]){
                                var temp=arr[i];  
                                arr[i]=arr[j];  
                                arr[j]=temp;  
                            }  
                        console.log("第"+(++times)+"次排序后:"+arr);  
                        }  
                    }   
                    return arr;  
                }  
                console.log(sortArr2(arr));  //[-10, 0, 2, 3, 20, 88, 90, 100, 102, 999]
    
    

    方法2执行过程中的结果:

    第1次排序后:0,90,-10,88,999,100,102,2,3,20
    第2次排序后:-10,90,0,88,999,100,102,2,3,20
    第3次排序后:-10,90,0,88,999,100,102,2,3,20
    第4次排序后:-10,90,0,88,999,100,102,2,3,20
    第5次排序后:-10,90,0,88,999,100,102,2,3,20
    第6次排序后:-10,90,0,88,999,100,102,2,3,20
    第7次排序后:-10,90,0,88,999,100,102,2,3,20
    第8次排序后:-10,90,0,88,999,100,102,2,3,20
    第9次排序后:-10,90,0,88,999,100,102,2,3,20
    第10次排序后:-10,0,90,88,999,100,102,2,3,20
    第11次排序后:-10,0,90,88,999,100,102,2,3,20
    第12次排序后:-10,0,90,88,999,100,102,2,3,20
    第13次排序后:-10,0,90,88,999,100,102,2,3,20
    第14次排序后:-10,0,90,88,999,100,102,2,3,20
    第15次排序后:-10,0,90,88,999,100,102,2,3,20
    第16次排序后:-10,0,90,88,999,100,102,2,3,20
    第17次排序后:-10,0,90,88,999,100,102,2,3,20
    第18次排序后:-10,0,88,90,999,100,102,2,3,20
    第19次排序后:-10,0,88,90,999,100,102,2,3,20
    第20次排序后:-10,0,88,90,999,100,102,2,3,20
    第21次排序后:-10,0,88,90,999,100,102,2,3,20
    第22次排序后:-10,0,2,90,999,100,102,88,3,20
    第23次排序后:-10,0,2,90,999,100,102,88,3,20
    第24次排序后:-10,0,2,90,999,100,102,88,3,20
    第25次排序后:-10,0,2,90,999,100,102,88,3,20
    第26次排序后:-10,0,2,90,999,100,102,88,3,20
    第27次排序后:-10,0,2,90,999,100,102,88,3,20
    第28次排序后:-10,0,2,88,999,100,102,90,3,20
    第29次排序后:-10,0,2,3,999,100,102,90,88,20
    第30次排序后:-10,0,2,3,999,100,102,90,88,20
    第31次排序后:-10,0,2,3,100,999,102,90,88,20
    第32次排序后:-10,0,2,3,100,999,102,90,88,20
    第33次排序后:-10,0,2,3,90,999,102,100,88,20
    第34次排序后:-10,0,2,3,88,999,102,100,90,20
    第35次排序后:-10,0,2,3,20,999,102,100,90,88
    第36次排序后:-10,0,2,3,20,102,999,100,90,88
    第37次排序后:-10,0,2,3,20,100,999,102,90,88
    第38次排序后:-10,0,2,3,20,90,999,102,100,88
    第39次排序后:-10,0,2,3,20,88,999,102,100,90
    第40次排序后:-10,0,2,3,20,88,102,999,100,90
    第41次排序后:-10,0,2,3,20,88,100,999,102,90
    第42次排序后:-10,0,2,3,20,88,90,999,102,100
    第43次排序后:-10,0,2,3,20,88,90,102,999,100
    第44次排序后:-10,0,2,3,20,88,90,100,999,102
    第45次排序后:-10,0,2,3,20,88,90,100,102,999

    总结分析:上面两种方法都实现了冒泡排序,比较的方式不一样,但是排序次数是一样的,10个数要对比45次。

    ---------------------------------------------此处是分割线----------------------------------------------

    讲完冒泡排序,下面一起来了解一下什么是快速排序,何谓快速?就是比较更少的次数得到一样的结果。

    方法一:先找到一个基准点(一般指数组的中部),然后数组被该基准点分为两部分,依次与该基准点的数字比较,

    如果比它小,放左边;反之,放右边。分别用一个空数组去存储比较后的数据。最后递归执行上述操作,直到数组长度<=1;

                var arr = [90,0,-10,88,99,1,102,2,3,200];
                var times=0;  
                var quickSort=function(arr){   
                    //如果数组长度小于等于1无需判断直接返回即可  
                    if(arr.length<=1){  
                        return arr;  
                    }  
                    var midIndex=Math.floor(arr.length/2);//取基准点  
                    var midIndexVal=arr.splice(midIndex,1);//取基准点的值,splice(index,1)函数可以返回数组中被删除的那个数arr[index+1]  
                    var left=[];//存放比基准点小的数组
                    var right=[];//存放比基准点大的数组  
                    //遍历数组,进行判断分配  
                    for(var i=0;i<arr.length;i++){  
                        if(arr[i]<midIndexVal){  
                            left.push(arr[i]);//比基准点小的放在左边数组  
                            console.log(left);
                        }  
                        else{  
                            right.push(arr[i]);//比基准点大的放在右边数组  
                            console.log(right);
                        }  
                        console.log("第"+(++times)+"次排序后:"+arr);  
                    }  
                    //递归执行以上操作,对左右两个数组进行操作,直到数组长度为<=1;  
                    return quickSort(left).concat(midIndexVal,quickSort(right));  
                };  
                    console.log(quickSort(arr));   //[-10, 0, 1, 2, 3, 88, 90, 99, 102, 200]

    经过测试,随便变换数组的数,比较的次数也会改变,比如上面的数组,比较了25次。

    而换成[90,0,-10,88,999,1,102,2,3,200],比较了22次,结果是[-10, 0, 1, 2, 3, 88, 90, 102, 200, 999]。

    再换成[90,0,-10,88,99,1,102,2,3,20] ,比较了30次,结果是[-10, 0, 1, 2, 3, 20, 88, 90, 99, 102]。

    方法二:直接利用数组的排序方法sort来实现

                    var count=0;
                    function sortNumber(a,b){   //定义排序规则
                        console.log(count++);  
                        return a-b;
                    }
                    console.log(arr.sort(sortNumber));  //数组排序方法sort

    同样的,经过测试,随便变换数组的数,比较的次数也会改变,比如上面的数组[90,0,-10,88,99,1,102,2,3,200];,比较了21次。

    而换成[90,0,-10,88,999,1,102,2,3,200],比较了23次,结果是[-10, 0, 1, 2, 3, 88, 90, 102, 200, 999]。

    再换成[90,0,-10,88,99,1,102,2,3,20] ,比较了25次,结果是[-10, 0, 1, 2, 3, 20, 88, 90, 99, 102]。

    总结分析:以上两种快速排序方法的比较次数都相对少,但是随着排序的数不一样,比较的次数也会不一样.

    最后对冒泡排序与快速排序两种方法进行对比分析:

    以上两种快速排序方法都比上面的冒泡排序的比较次数少,效率高。

    但是冒泡排序简单实用易于理解,而直接使用数组方法则更加简单快捷高效率的解决排序问题.

    以上仅代表个人的见解,如果不对的地方希望大家指出.或者有更好的解决方法也希望可以分享出来学习.

  • 相关阅读:
    LeetCode 121. Best Time to Buy and Sell Stock
    LeetCode 221. Maximal Square
    LeetCode 152. Maximum Product Subarray
    LeetCode 53. Maximum Subarray
    LeetCode 91. Decode Ways
    LeetCode 64. Minimum Path Sum
    LeetCode 264. Ugly Number II
    LeetCode 263. Ugly Number
    LeetCode 50. Pow(x, n)
    LeetCode 279. Perfect Squares
  • 原文地址:https://www.cnblogs.com/stella1024/p/7487099.html
Copyright © 2020-2023  润新知