zoukankan      html  css  js  c++  java
  • 技术分享:基本排序算法

     前言:

     今天我给大家分享一点排序算法的知识。大概要花30分钟的时间,我尽量控制在20分钟左右。

    首先,我想问大家一个问题,你们知道的排序算法有哪些?冒泡排序?快速排序?

    那你们知道它们之间的差异是什么?有的快有的慢对吧?没错,排序算法分为基本排序算法和高级排序算法。我今天要讲的就是基本排序算法。请看下面的目录。

    技术主题:基本排序算法

    目录:

    一、冒泡排序

    1. 原理
    2. 实现方法

    二、选择排序

    1. 原理
    2. 实现方法

    三、插入排序

    1. 原理
    2. 实现方法

    四、如何通过测试来比较这三种算法的速度?

    五、其他(有时间的话就讲)

    【问题1】sort()方法用的是什么排序算法?

    【问题2】for循环中++i 和 i++ 的区别?

     基本排序算法有三种,冒泡排序、选择排序、插入排序。我会依次讲它们的原理和实现方法。最后会讲下如何比较它们的排序速度。

    冒泡排序

    我们先来看冒泡排序,冒泡排序是最基本的排序算法,也是最慢的。

    它的原理是什么呢?我用表格给大家演示。更直观。(打开表格,随机输入一串数据)

     从第一个数字开始,和它相邻的数字比较,左边比右边大就交换。一直重复这个过程,直到最大的数字移到最右端。

     不知道大家听懂了没有?有问题可以提出来哦。没问题的话,那我给大家看下代码怎么实现这种算法。看完代码我再给大家演示一遍也可以。

    function swap(arr, index1, index2) {
        var temp = arr[index1];
        arr[index1] = arr[index2];
        arr[index2] = temp;
    }
    
    
    /**冒泡排序 */
    function bubbleSort(arr) {
        for (var outer = arr.length; outer >= 2; --outer) {
            console.log(arr.toString());
            for (var inner = 0; inner <= outer - 1; ++inner) {
                if (arr[inner] > arr[inner+1]) {
                    swap(arr, inner, inner + 1);
                }
            }
        }
        console.log(arr.toString());
    }
    
    
    /**选择排序 */
    function selectionSort(arr) {
        var min;
        for (var outer = 0; outer < arr.length - 1; ++outer) {
            console.log(arr.toString());
            min = outer;
            for (var inner = outer + 1; inner < arr.length; ++inner) {
                if (arr[inner] < arr[min]) {
                    min = inner;
                }
            }
            swap(arr, outer, min);
        }
        console.log(arr.toString());
    }
    
    /**插入排序 */
    function insertionSort(arr) {
        var temp, inner;
        for (var outer = 1; outer <= arr.length - 1; ++outer) {
            console.log(arr.toString());
            temp = arr[outer];
            inner = outer;
            while(inner > 0 && (arr[inner-1] >= temp)) {
                arr[inner] = arr[inner - 1];
                --inner;
            }
            arr[inner] = temp;
        }
        console.log(arr.toString());
    }

    这里有3个函数。分别用来实现冒泡排序、选择排序、插入排序。

    我先讲一下他们的共同点,第一、都是嵌套循环,第二、都用到了交换函数swap,请看swap的代码。

    swap函数

    function swap(arr, index1, index2) {
        var temp = arr[index1];
        arr[index1] = arr[index2];
        arr[index2] = temp;
    }

    现在看下冒泡排序函数

    /**冒泡排序 */
    function bubbleSort(arr) {
        for (var outer = arr.length; outer >= 2; --outer) {
            console.log(arr.toString());
            for (var inner = 0; inner <= outer - 1; ++inner) {
                if (arr[inner] > arr[inner+1]) {
                    swap(arr, inner, inner + 1);
                }
            }
        }
        console.log(arr.toString());
    }

    外层的for循环是用来控制内层for循环的长度的。所以它是递减的。

    (。。。。)讲完后

    我再给大家用表格演示一遍冒泡排序的过程,一边对照代码一边演示

    现在用代码执行一遍,看看代码执行的冒泡排序和我演示的过程是不是一致的。执行结果如下:

    大家有什么问题吗?没有的话我继续讲选择排序。
    (时间有限,我得快点讲)

    选择排序

    请看表格。

     请看代码。

    /**选择排序 */
    function selectionSort(arr) {
        var min;
        for (var outer = 0; outer < arr.length - 1; ++outer) {
            console.log(arr.toString());
            min = outer;
            for (var inner = outer + 1; inner < arr.length; ++inner) {
                if (arr[inner] < arr[min]) {
                    min = inner;
                }
            }
            swap(arr, outer, min);
        }
        console.log(arr.toString());
    }

    同样也用代码验证一下[9, 2, 6, 3, 8, 0]

     有些循环输出的结果和上一次是一样的,我在表格中省略掉了。

    选择排序就是这样。大家有什么疑问吗?要不要我用表格再演示一遍。没有的话我继续讲插入排序。

    插入排序

    请看表格,还是这一组数据。

     看下插入排序的方法

    /**插入排序 */
    function insertionSort(arr) {
        var temp, inner;
        for (var outer = 1; outer <= arr.length - 1; ++outer) {
            console.log(arr.toString());
            temp = arr[outer];
            inner = outer;
            while(inner > 0 && (arr[inner-1] >= temp)) {
                arr[inner] = arr[inner - 1];
                --inner;
            }
            arr[inner] = temp;
        }
        console.log(arr.toString());
    }

    代码验证一下

    到这里三种基本排序算法都讲完了。

    你们都听懂了吗?我提个问题吧,你们觉得哪一种排序算法好?

    我们需要一个客观的衡量。

    这三种排序算法的复杂度非常相似。从理论上来说,他们的执行效率也应该差不多。现在我们就做一个测试来比较它们的效率,看看到底哪个更快。

    这个测试怎么来做呢?我们不可能手动输入1000,10000个数据来测试。所以,

    首先我们要准备2个工具。一个可以生成随机数组的类。还有一个问题是如何计时。这个等下再说。先看怎么生成数组。

    function CArray(numElements) {
        this.dataStore = [];
        this.pos = 0;
        this.numElements = numElements;
        this.toString = toString;
        this.setData = setData;
        this.swap = swap; // 交换方法
        this.bubbleSort = bubbleSort; // 冒泡排序
        this.selectionSort = selectionSort; // 选择排序
        this.insertionSort = insertionSort; // 插入排序
    
        for (var i = 0; i < numElements; ++i) {
            this.dataStore[i] = i;
        }
    }
    
    function setData() {
        for (var i = 0; i < this.numElements; ++i) {
            this.dataStore[i] = Math.floor(Math.random() * (this.numElements + 1)); // 这里为什么要+1?
        }
    }
    
    function toString() {
        var restr = '';
        for (var i = 0; i < this.dataStore.length; ++i) {
            restr += this.dataStore[i] + ' ';
            if (i > 0 & i % 10 == 0) {
                restr += '
    '
            }
        }
        return restr;
    }
    
    function swap(arr, index1, index2) {
        var temp = arr[index1];
        arr[index1] = arr[index2];
        arr[index2] = temp;
    }
    
    /**冒泡排序 */
    function bubbleSort() {
        var len = this.dataStore.length;
        for (var outer = len; outer >= 2; --outer) {
            for (var inner = 0; inner <= outer - 1; ++inner) {
                if (this.dataStore[inner] > this.dataStore[inner+1]) {
                    swap(this.dataStore, inner, inner + 1);
                }
            }
        }
    }
    
    /**选择排序 */
    function selectionSort() {
        var min;
        for (var outer = 0; outer <= this.dataStore.length - 2; ++outer) {
            min = outer;
            for (var inner = outer + 1; inner <= this.dataStore.length - 1; ++inner) {
                if (this.dataStore[inner] < this.dataStore[min]) {
                    min = inner;
                }
            }
            swap(this.dataStore, outer, min);
        }
    }
    
    /**插入排序 */
    function insertionSort() {
        var temp, inner;
        for (var outer = 1; outer <= this.dataStore.length - 1; ++outer) {
            temp = this.dataStore[outer];
            inner = outer;
            while(inner > 0 && (this.dataStore[inner-1] >= temp)) {
                this.dataStore[inner] = this.dataStore[inner - 1];
                --inner;
            }
            this.dataStore[inner] = temp;
        }
    }

    这里面的冒泡排序、选择排序和插入排序的三个方法和上面用的稍微有些区别,那就是不用传入数组,直接调用实例上的内置方法。其他都一样。

    我们先来生成一个长度100,值为0-100之间的数组。

    为了节省时间,这些代码我都提前准备好了。请看

    var numElements = 100;
    var nums = new CArray(numElements);
    nums.setData();
    console.log(nums.toString());

    结果如下:

    现在数据准备好了。我们来看计时怎么写?

    先给大家看一个小例子

    var start = new Date().getTime();
    for (var i = 1; i < 1000; ++i) {
        console.log(i);
    }
    var stop = new Date().getTime();
    var elapsed = stop - start;
    console.log('消耗的时间为:' + elapsed + ' 毫秒');

    运行一下就可以看到这个简单的for循环执行需要时间

    最后把这个计时方法用到排序算法测速上。

    var start = new Date().getTime();
    nums.bubbleSort();
    var stop = new Date().getTime();
    var elapsed = stop - start;
    console.log(numElements + ' 个元素执行【冒泡排序】消耗的时间为:' + elapsed + ' 毫秒');
    
    start = new Date().getTime();
    nums.selectionSort();
    stop = new Date().getTime();
    elapsed = stop - start;
    console.log(numElements + ' 个元素执行【选择排序】消耗的时间为:' + elapsed + ' 毫秒');
    
    start = new Date().getTime();
    nums.insertionSort();
    stop = new Date().getTime();
    elapsed = stop - start;
    console.log(numElements + ' 个元素执行【插入排序】消耗的时间为:' + elapsed + ' 毫秒');

    先看下100个数据三种排序算法的速度分别是多少?

    结果如下:

     差不多。

    再看1000个数据的情况,把numElements的值改成1000.

     差距已经出来了。再看看10000个数据如何?

     这个差距非常明显了。

    今天的主要内容就是这些。大家有什么疑问可以提出来。

    有时间的话,我想提个问题,你们知道sort()用的什么排序算法吗?

    【答】

    ECMAScript没有定义使用哪种排序算法,各个浏览器的实现方式会有不同。火狐中使用的是归并排序,Chrome使用的是插入排序和快速排序的结合排序算法。数组长度不超过10时,使用插入排序。超过10则用快速排序。因为在数组较短时插入排序更有效。

    今天的分享到此结束,谢谢大家!

  • 相关阅读:
    20 模块之 re subprocess
    19 模块之shelve xml haslib configparser
    18 包 ,logging模块使用
    vue项目的搭建使用
    课程模块表结构
    DRF分页组件
    Django ContentType组件
    跨域
    解析器和渲染器
    DRF 权限 频率
  • 原文地址:https://www.cnblogs.com/cathy1024/p/12996523.html
Copyright © 2011-2022 走看看