JavaScript 算法学习 【排序算法】

目录

一、冒泡排序

冒泡排序的效率(对于N个数据项  )

二、选择排序

选择排序的效率 

三、插入排序

插入排序的效率

四、希尔排序

 希尔排序的思路

五、快速排序 非常重要

快速排序的效率 


 <script>
        //创建列表类
        function ArrayList() {
            //属性
            this.array = []

            //方法
            //将数据可以插入到数组中的方法
            ArrayList.prototype.insert = function(item) {
                this.array.push(item)
            }

            //toString
            ArrayList.prototype.toString = function() {
                return this.array.join('-')
            }

           ArrayList.prototype.swap = function(m, n) {
                var temp = this.array[m]
                this.array[m] = this.array[n]
                this.array[n] = temp
            }
 
      }
 </script>

一、冒泡排序

//冒泡排序
            ArrayList.prototype.bubblesort = function() {
                    //1.获取数组的长度
                    var length = this.array.length;
                    //第一次进来:i=0,比较i=0和i=1位置的两个数据,如果0位置大
                    //最后一次进来:i=length-2;比较length-2和length-1
                    for (var j = length - 1; j >= 0; j--) {
                        for (var i = 0; i < j; i++) {
                            if (this.array[i] > this.array[i + 1]) {
                                //交换两个数据的位置
                                var temp = this.array[i]
                                this.array[i] = this.array[i + 1];
                                this.array[i + 1] = temp;
                            }
                        }
                    }
                }

冒泡排序的效率(对于N个数据项  )

1.比较次数

(N-1)+(N-2)+(N-3)+...+1=N*(N-1)/2

大O形式为:O(N^2)

2.交换次数

真实次数N*(N-1)/4,常量不算在大O表示法中,最终可认为是O(N^2)

二、选择排序

                                    

每次选择出符合要求的

思路:

选定第一个索引位置,然后和后面元素依次比较

如果后面的元素,小于第一个索引未知的元素,交换位置

经过一轮的比较后,可以确定第一个位置是最小的

然后使用同样的方法剩下的元素逐个比较即可

可以看出选择排序,第一轮会选出最小值,第二轮会选出第二下的值


            //选择排序
            ArrayList.prototype.selectsort = function() {
                //1.获取数组的长度
                var length = this.array.length;
                //2. 外层循环:从0位置开始取出数据,直到length - 2位置
                for (j = 0; j < length - 1; j++) {
                    var min = j;
                 //3.内层循环:从i+1位置开始,和后面的内容比较
                    for (var i = min + 1; i < length; i++) {
                        if (this.array[min] > this.array[i]) {
                            min = i
                        }
                    }
                    this.swap(min, j)
                }
            }

选择排序的效率 

1.比较次数

真实次数N*(N-1)/2,大O形式为:O(N^2)

2.交换次数:

选择排序每次进行选择的时候,最多交换一次,一共遍历N-1次

选择排序的交换次数只有N-1次,大O表示法:O(N)

三、插入排序

              

           //插入排序
            ArrayList.prototype.insertionSort = function() {
                //1.获取数组的长度
                var length = this.array.length;
                //2.外层循环:从第一个位置开始获取数据,向前面局部有序进行插入
                for (var i = 1; i < length; i++) {
                    //3. 内层循环,获取位置i的元素,和前面的数据依次进行比较
                    var temp = this.array[i]
                    var j = i;
                    while (this.array[j - 1] > temp && j > 0) {
                        this.array[j] = this.array[j - 1]
                        j--
                    }

                    // //4.将j位置的数据,放置temp
                    this.array[j] = temp
                }
            }

插入排序的效率

1.比较次数

第一趟需要的最多次数是1,第二趟最多次数是2,依次类推,最后一趟是N-1次

所以最多次数是:1+2+3+4+...+N-1=N*(N-1)/2

每趟发现插入点之前,平均只有全体数据项的一半需要进行比较,所以比较次数是:

N*(N-1)/4

2.复制次数

做多是:N*(N-1)/2

平均次数是

N*(N-1)/4

四、希尔排序

希尔排序是插入排序的一种高效的改进版,并且效率比插入排序更快

希尔排序的历史~

 希尔排序的思路

希尔排序是基于插入排序,

首先来看一下插入排序存在的问题:

假设一个很小的数据项在很靠近右端的位置,本来这里应该是较大的数据项的位置,把这个小数据项移动到左边的正确位置,所有的中间项数据都必须向右移动一位,这样执行效率很低。

希尔排序的思路:

比如下面的数组:81,94,11,96,12,35,17,95,28,58,41,75,15


            //希尔排序
            ArrayList.prototype.shellSort = function() {
                //1.获取数组的长度
                var length = this.array.length;
                //2. 初始化增量
                var gap = Math.floor(length / 2)
                    //3. while(gap不断减小)
                while (gap >= 1) {
                    //4.以gap作为间隔,进行分组,对分组进行插入排序
                    for (var i = gap; i < length; i++) {
                        var temp = this.array[i]
                        var j = i
                        while (this.array[j - gap] > temp && j > gap - 1) {
                            this.array[j] = this.array[j - gap]
                            j -= gap
                        }
                        //5.将j位置的元素复制temp
                        this.array[j] = temp
                    }
                    //6.增量变化/2
                    gap = Math.floor(gap / 2)
                }
            }

 希尔排序的效率

最坏的情况下,时间复杂度为O(N^2),通常情况下都好于O(N^2)

五、快速排序 非常重要

快速排序可以看成冒泡排序的升级版

基本思想:

选定pivot中心轴

将大于pivot的数字放在Pivot的右边

将小于pivot的数字放在Pivot的左边

分别对左右子序列重复前三步的操作

以第一个数为基准数快速排序算法javascript实现_wiilman的博客-CSDN博客_js快速排序算法

  function quick_sort(arr, from, to) {
            var i = from; //哨兵i
            var j = to; //哨兵j
            var key = arr[from]; //标准值
            if (from >= to) { //如果数组只有一个元素
                return;
            }
            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);
        }

选中间值作为pivot

 // 1. 选择枢纽
            ArrayList.prototype.medium = function(left, right) {
                // 1. 取出中间的位置
                var center = Math.floor((left + right) / 2);

                // 2. 判断大小,并且进行交换
                if (this.array[left] > this.array[center]) {
                    this.swap(left, center);
                };
                if (this.array[left] > this.array[right]) {
                    this.swap(left, right);
                };
                if (this.array[center] > this.array[right]) {
                    this.swap(center, right);
                };

                // 3.将center换到right-1的位置
                this.swap(center, right - 1)

                return this.array[right - 1]
            };

            // 2. 快速排序的实现
            ArrayList.prototype.quickSort = function() {
                this.quick(0, this.array.length - 1);

            };

            ArrayList.prototype.quick = function(left, right) {
                // 1. 结束条件
                if (left >= right) {
                    return
                };

                // 2. 获取枢纽
                var pivot = this.medium(left, right);

                // 3. 定义变量,用于当前找到的位置
                var i = left;
                var j = right - 1;

                // 4. 开始进行交换
                while (i < j) {
                    while (this.array[++i] < pivot) {};
                    while (this.array[--j] > pivot) {};
                    if (i < j) {
                        this.swap(i, j);
                    } else {
                        break;
                    };
                }
                // 5. 将枢纽放置在正确的位置,i的位置
                this.swap(i, right - 1);

                // 6. 分而治之
                this.quick(left, i - 1);
                this.quick(i + 1, right);
            };

快速排序的效率 

最坏的情况:

每次枢纽选择都是最左边或者最右边,效率等同于冒泡排序

快速排序的平均效率:

O(N*logN)

稳定的排序算法:冒泡排序、直接插入排序、归并排序
不稳定的排序算法:选择排序、希尔排序、快速排序、堆排序 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值