整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

算法学习-JavaScript冒泡排序与选择排序

算法学习-JavaScript冒泡排序与选择排序

法与数据结构构成了程序,数据结构用于实现数据的表示、存储、管理,算法通过使用数据完成一定的业务逻辑与操作,最终实现了程序的功能。因此算法在编程中的重要性是不言而喻的。很多复杂的算法都是借助最基本的算法实现的。本文主要选取经典排序算法中的冒泡排序与选择排序对JavaScript编程实现算法进行简单描述与说明。

程序算法


算法说明

算法(Algorithm)是解决问题的一种策略机制,算法也是有限操作指令的集合。按照算法策略输入符合要求的数据,最终获得解决问题的输出结果。冒泡算法与选择算法主要用于实现对无序的数字集合进行排序。算法描述分别如下:

1、冒泡排序算法

冒泡算法顾名思义,可以将待排序序列中的每一个元素看成一个个气泡,假设气泡的大小用元素的数值表示,这样的话最大气泡(最大的元素数字)会最先升起来,这一过程即为冒泡。冒泡算法的关键在于将未排序部分最大元素依次后移动,在序列尾端从小到大形成排序好的有序序列。冒泡排序示意如下图所示:

冒泡排序算法示意图

冒泡排序算法示意图如上图所示,其中每一行表示一次排序,排序目的找到最大值,从待排序序列中取出最大值,放到红色小球区域中,红色小球区域表示已完成排序的序列。通过上图我们可以看出,每趟排序冒泡出来的元素分别为(17,12,9,5,1)。最终排好的序列为(1,5,9,12,17)。

2、选择排序算法

选择排序是指从未排序的序列中找到最小的值并取出放到已经排好顺序的序列中,一直到未排序序列中的元素个数为零。即所有的元素都放到已经排好顺序的序列中。该算法的关键在于从未排序的序列中找到最轻(数值最小)元素,放到已经排序好的序列中。选择排序算法示意如下图所示:

选择排序示意图

选择排序示意图如上图所示,选择的关键在于找到最小的值,并将其放到已经排序好的序列中。上图中未排序(待排序)集合为黄色部分,排序好的部分为绿色背景部分,每一行为一次排序,排序目的找到最小元素。通过上图可知选择出来的最小值依次为(1,5,9,12,17)。

冒泡排序实现

JavaScript冒泡排序主要借助JavaScript array数字对象实现待排序序列的存储,通过循环语句遍历数组,从待排序序列的第一个元素开始与后面元素比较,如大于后面元素则交换,因此经过一趟遍历,最大元素将会跑到array数组的末尾。实现代码描述如下:

 var arr1=[9,1,4,13,7,8,20,23,15]; 
 var wlen1=arr1.length;
 var count1=0;//记录总执行次数 
 for(var i=0;i<arr1.length-1;i++) { 
 for(var j=0;j<wlen1;j++) { 
 if(arr1[j]>arr1[j+1]) { 
 var temp; 
 temp=arr1[j]; 
 arr1[j]=arr1[j+1]; 
 arr1[j+1]=temp; 
 count1++; 
 } 
 } 
 wlen1=wlen1-1; 
 }

选择排序实现

按照算法描述选择排序需要使用两个JavaScript数组对象,一个为待排序序列存储数据,一个为排序完成数组。分别从待排序序列数组中找到最小值并取出存储到完成排序数组中。arr数组为待排序数组,res数组为排序完成数组。使用javaScript实现选择排序代码描述如下:

 var arr=[9,1,4,13,7,8,20,23,15]; 
 var wlen=arr.length; 
 var count=0;//记录已完成排序元素数量 
 var res=[];//最终排序结果数组 
 var minvalue=0; //思路从未排序序列选择最小元素放到已经完成排序的数组中 
 for(var i=0;i<wlen;i++) { //找到最小元素 
 minvalue=arr[0]; 
 for(var j=0;j<arr.length;j++) { 
 if(minvalue>arr[j]) { 
 minvalue=arr[j]; 
 var temp; 
 temp=arr[0]; 
 arr[0]=arr[j]; 
 arr[j]=temp; 
 } 
 count++; 
 } 
 arr.shift(); 
 res[i]=minvalue; 
 }

JavaScript实现基本冒泡与选择排序算法描述如上所示,本例设计测试用例为(9,1,4,13,7,8,20,23,15),该待排序测试用例分别执行冒泡排序与选择排序,效果展示如下图

冒泡排序与选择测试结果


本头条号长期关注编程资讯分享;编程课程、素材、代码分享及编程培训。如果您对以上方面有兴趣或代码错误、建议与意见,可以联系作者,共同探讨。期待大家关注!本文分类类别:算法学习|javasScript编程。


@Author:Runsen」

插入排序

插入排序(英语:Insertion Sort)是一种简单直观的排序算法。

一个有序的数组,我们往里面添加一个新的数据后,如何继续保持数据有序呢?很简单,我们只要遍历数组,找到数据应该插入的位置将其插入即可。

图片来自王争算法专栏

通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

插入排序在实现上,在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

因此,代码编写需要判断插入元素和当前元素的大小关系,遍历时需要从数组的第二个数开始。

如果插入元素大于当前元素,则将待插入元素插入到当前元素的后一位。

如果插入元素小于当前元素,则将当前元素后移一位。直到找到一个当前元素小于插入元素。

因此,在for循环遍历时,又有一个while内循环的条件,条件的内容是插入元素的索引减一进行对比。如果插入元素小于当前元素,同时对索引进行减一操作。如果出现了索引等于零的情况,那么表示插入元素等于当前元素。

下面是插入排序的具体Python代码。

def insert_sort(a):
    length = len(a)
    if length <= 1:
        return a
    # 从数组的第二个数开始
    for i in range(1, length):
        # 从后向前扫描
        j = i - 1
        # value指的是插入元素
        value = a[i]
        while j >= 0:
            if a[j] < value:
                # 插入元素大于当前元素,则将待插入元素插入到当前元素的后一位
                a[j + 1] = value
                break
            else:
                # 插入元素小于当前元素,则将当前元素后移一位
                a[j + 1] = a[j]
                if j == 0:
                    a[j] = value
            j -= 1
    return a


def insertionSort(arr):
    # 对上面的代码进行简单化
    for i in range(len(arr)):
        preIndex = i - 1
        current = arr[i]
        while preIndex >= 0 and arr[preIndex] > current:
            arr[preIndex + 1] = arr[preIndex]
            preIndex -= 1
        arr[preIndex + 1] = current
    return arr

if __name__ == '__main__':
    nums = [54, 26, 93, 17, 77, 31, 44, 55, 20]
    insert_sort(nums)
    print(nums) # [17, 20, 26, 31, 44, 54, 55, 77, 93]

下面对Python代码改为Java代码。代码来自菜鸟教程。

// Java
import java.util.Arrays;

public class Solution {
    public static void main(String[] args) {
        InsertSort(new int[] { 9 ,20 , 10, 13 , 12});
    }
    public static void InsertSort(int [] arr){
        int value; //待插入元素
        int index; //初始值为待插入元素前一个元素的索引

        for(int i= 1 ; i< arr.length;i++){
            //i从第二个元素开始,默认第一个元素是有序的
            //循环条件是小于数组长度,因为也要将最后一个元素插入到前面的序列
            value = arr[i];
            index = i - 1;//初始为前一个元素
            while(index >=0 && value < arr[index]){
                //需要保证index合法
                //每当前面的元素比待插入元素大,就向后移动
                arr[index + 1] = arr[index];
                //不用怕覆盖,因为value保存着待插入的值
                index--;
            }
            //当退出循环,表明已经找到了待插入位置,即index + 1
            arr[index + 1] = value;
        }

        System.out.println(Arrays.toString(arr));
    }
}

下面对Python代码改为JavaScript代码。代码来自菜鸟教程。

// JavaScript
function insertionSort(arr) {
    var len = arr.length;
    // JavaScript需要声明变量先
    var preIndex, current;
    for (var i = 1; i < len; i++) {
        preIndex = i - 1;
        current = arr[i];
        while(preIndex >= 0 && arr[preIndex] > current) {
            arr[preIndex+1] = arr[preIndex];
            preIndex--;
        }
        arr[preIndex+1] = current;
    }
    return arr;
}

对于不同的查找插入点方法(从头到尾、从尾到头),元素的比较次数是有区别的。但对于一个给定的初始序列,移动操作的次数总是固定的,就等于逆序度。

在插入排序中,对于值相同的元素,我们可以选择将后面出现的元素,插入到前面出现元素的后面,这样就可以保持原有的前后顺序不变,所以插入排序是稳定的排序算法。

对于插入排序来说,每次插入操作都相当于在数组中插入一个数据,循环执行 n 次插入操作,所以平均时间复杂度为 O(n2)

如果输入数组已经是排好序的话,插入排序出现最佳情况,其运行时间是输入规模的一个线性函数,其时间代价是O(n)

如果输入数组是逆序排列的,将出现最坏情况。平均情况与最坏情况一样,其时间代价是 O(n2)

参考:https://www.runoob.com/w3cnote/insertion-sort.html

选择排序

选择排序(Selection sort)是一种简单直观的排序算法。

选择排序算法的实现思路有点类似插入排序,也分已排序区间和未排序区间。但是选择排序每次会从未排序区间中找到最小的元素,将其放到已排序区间的末尾。

它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

选择排序:首先搜索整个列表,找到最小项的位置,如果该位置不是列表的第1项,就交换这两个位置的元素。然后从列表的第2个元素开始,重复上述过程,直到算法达到整个过程的最后一个位置,图形解释如下

图片来自王争算法专栏

选择排序还有一种代码的形式是将最大值逐一选择到后面,因此遍历的时候需要逆序遍历。

def selection_sort1(nums):
    # 思路是将最小值逐一选择到前面
    n = len(nums)
    # 第一层for表示循环选择的遍数

    for i in range(n - 1):
        min_index = i  # 记录最小值的位置
        # 第二层for表示最小元素和后面的元素逐个比较

        for j in range(i + 1, n):
            if nums[j] < nums[min_index]:
                min_index = j
        if min_index != i:
           # 查找一遍后将最小元素与起始元素互换
            nums[i], nums[min_index] = nums[min_index], nums[i]

def selection_sort2(nums):
    # 思路是将最大值逐一选择到后面
    n = len(nums)
    for i in range(n - 1, 0, -1):
        max_index = i  # 记录最大值的位置
        for j in range(i):
            if nums[j] > nums[max_index]:
                max_index = j
        if max_index != i:
            nums[i], nums[max_index] = nums[max_index], nums[i]

下面对Python代码改为Java代码。代码来自菜鸟教程,选择第一种思路。

下面对Python代码改为JavaScript代码。代码来自菜鸟教程。

function selectionSort(arr) {
    var len = arr.length;
    var minIndex, temp;
    for (var i = 0; i < len - 1; i++) {
        minIndex = i;
        for (var j = i + 1; j < len; j++) {
            if (arr[j] < arr[minIndex]) {     // 寻找最小的数
                minIndex = j;                 // 将最小数的索引保存
            }
        }
        temp = arr[i];
        arr[i] = arr[minIndex];
        arr[minIndex] = temp;
    }
    return arr;
}

选择排序是一种不稳定的排序算法。选择排序每次都要找剩余未排序元素中的最小值,并和前面的元素交换位置,这样破坏了稳定性。

当出现几个值相同的时候,比如 5,8,5,2,9这样一组数据,使用选择排序算法来排序的话,第一次找到最小元素 2,与第一个 5 交换位置,那第一个 5 和中间的 5 顺序就变了,所以就不稳定了。

选择排序的主要优点与数据移动有关。如果某个元素位于正确的最终位置上,则它不会被移动。选择排序每次交换一对元素。

它们当中至少有一个将被移到其最终位置上,因此对n个元素的表进行排序总共进行至多n-1次交换。在所有的完全依靠交换。

无论数列初始状态怎样,在第 i 趟排序中选出最小关键字的记录,需做n-i次比较,因此,总的比较次数为:n(n-1)/2=O(n2)

因此直接选择排序的平均时间复杂度为 O(n2)。直接选择排序是一个就地排序,空间复杂度为S(n)=O(1)

参考:https://www.runoob.com/w3cnote/selection-sort.html

参考:极客时间王争算法专栏

总结 来自极客时间王争算法专栏

?

本文已收录 GitHub,传送门~[1] ,里面更有大厂面试完整考点,欢迎 Star。

?


Reference

[1]

传送门~: https://github.com/MaoliRUNsen/runsenlearnpy100

冒泡排序概述

冒泡排序是通过遍历待排序的数列,一次比较两个元素,根据大小调换位置,直到把最大的或最小的冒出来的排序方式。与选择排序、插入排序是比较常见的排序方式,也非常好理解。

冒泡排序平均时间复杂度是:O(n^2)

  • 步骤是:

1、先建立两个循环,外循环用于遍历整个数组,内循环遍历待排序的区间。

2、内循环每次都从第一项开始,将该项与后项进行比较,再两两交换,一直到待排序结尾。

3、重复第二项,一直到数组遍历完。

可以看成是用手捏住第一个位置,往右边一个一个比较交换,把最大或最小的找出来,放在最后1位。然后再拿第一位置的数字,逐个比较,找出第二大的数字来放在倒数第2的位置。以此类推,把所有的数字都筛选一遍即可。

冒泡排序执行过程分析

冒泡排序实现

  • 自左往右逐个将最大项冒出:

两个循环,外循环是整个数列,内循环是数列减去已排好序的数列。

  • 自右往左逐个将最小项冒出:

冒泡排序的优化

  • 加入一个标记,用来记录上一趟排序中是否发生过交换,如果没有进行过交换,说明当前数组已经排好序了,则不必再继续后面的遍历。