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


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

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

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

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

           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]。

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

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

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

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

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

  • 相关阅读:
    12. nc/netcat 用法举例
    7. 由一道ctf学习变量覆盖漏洞
    11. 几点基于Web日志的Webshell检测思路
    约瑟夫环
    栈结构的经典算法题
    二叉查找树之二
    fork与vfork
    数组常见算法题
    赛马问题
    fibonacci 数列及其应用
  • 原文地址:https://www.cnblogs.com/stella1024/p/7487099.html
Copyright © 2020-2023  润新知