栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 软件开发 > 后端开发 > Java

常见的排序算法

Java 更新时间:发布时间: 百科书网 趣学号

今天来学习一下数据结构课程中非常重要的排序算法。

我们学习一下一些常见的排序算法,如冒泡排序、选择排序、快速排序等。

1、冒泡排序

实现思路:

  • 对未排序的各元素从头到尾依次比较相邻的两个元素大小关系

  • 如果左边的队员大, 则两队员交换位置

  • 向右移动一个位置, 比较下面两个队员

  • 当走到最右端时, 最大的队员一定被放在了最右边

  • 按照这个思路, 从最左端重新开始, 这次走到倒数第二个位置的队员即可.

  • 依次类推, 就可以将数据排序完成

我们用数组来存放每一项数据,每次又从左端开始称为新的一趟,排序的趟数为数组长度减一;第一趟比较的次数也是数组长度减一,每增加一趟比较次数就会对应减一。

知道了这些我们通过代码实现:

 //排序数组
        var arr=[5,4,2,14,7,3,9]
        //趟数
        for (let i = 0; i < arr.length-1; i++) {
            //每一趟的比较次数
            for (let j = 0; j < arr.length-1-i; j++) {
                if (arr[j]>arr[j+1]) {
                    let temp=arr[j]
                    arr[j]=arr[j+1]
                    arr[j+1]=temp
                }
            }
        }
        console.log(arr);//[2, 3, 4, 5, 7, 9, 14]

2、选择排序

选择排序改进了冒泡排序, 将交换的次数由O(N²)减少到O(N), 但是比较的次数依然是O(N²)

实现思路:

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

  • 如果后面的队员, 小于第一个索引位置的队员, 则交换位置

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

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

  • 可以看出选择排序,第一轮会选出最小值,第二轮会选出第二小的值,直到最后

排序的趟数也是数组的长度-1,每一趟将找到对应的最小值依次从前往后排。

代码实现:

    var arr=[5,4,2,14,7,3,9]
        //趟数
        for (let i = 0; i < arr.length-1; i++) {
          //最小值
          let min=i
          //判断每次的最小值
          for (let j = i+1; j < arr.length; j++) {
            if (arr[min]>arr[j]) {
                min=j
            }
          }
            //将初始设定的最小值与找到的最小值交互
            let temp=arr[min]
            arr[min]=arr[i]
            arr[i]=temp
        }
        console.log(arr);

 3、插叙排序

插入排序是简单排序中效率最好的一种.

插入排序也是学习其他高级排序的基础, 比如希尔排序/快速排序, 所以也非常重要.

插叙排序的实现的核心是局部排序

局部排序:比如在一个队列中的人, 我们选择其中一个作为标记的队员. 这个被标记的队员左边的所有队员已经是局部有序的.

这意味着, 有一部门人是按顺序排列好的. 有一部分还没有顺序.

实现思路:

  • 从第一个元素开始,该元素可以认为已经被排序

  • 取出下一个元素,在已经排序的元素序列中从后向前扫描

  • 如果该元素(已排序)大于新元素,将该元素移到下一位置

  • 重复上一个步骤,直到找到已排序的元素小于或者等于新元素的位置

  • 将新元素插入到该位置后, 重复上面的步骤.

实现代码:

var arr = [5, 4, 2, 14, 7, 3, 9]
        //循环判断每一个元素
        for (let i = 1; i < arr.length; i++) {
            //从下标1开始,因为最开始数组第一个元素即下标取0的元素默认以及排好序了

            let j = i
            //设置一个变量标记一下每次插入的那个元素
            let mark = arr[i]
            // console.log(mark);
            while (j > 0 && arr[j - 1] > mark) {
                //直到找到合适的位置才会跳出循环
                arr[j] = arr[j - 1]
                j-- //向前找
            }
            //把我们要插入的那个元素插入到我们找到的位置
            arr[j] = mark
        }
        console.log(arr);

高级排序 快速排序

快速排序几乎可以说是目前所有排序算法中, 最快的一种排序算法.

当然, 没有任何一种算法是在任意情况下都是最优的, 比如希尔排序确实在某些情况下可能好于快速排序. 但是大多数情况下, 快速排序还是比较好的选择.

快速排序是什么?

  • 快速排序其实是我们学习过的最慢的冒泡排序的升级版.

  • 我们知道冒泡排序需要经过很多次交换, 才能在一次循环中, 将最大值放在正确的位置.

  • 而快速排序可以在一次循环中(其实是递归调用)找出某个元素的正确位置, 并且该元素之后不需要任何移动.

快速排序的思想:

  • 快速排序最重要的思想是分而治之.

  • 比如我们下面有这样一顿数字需要排序:

    • 第一步: 从其中选出了65. (其实可以是选出任意的数字, 我们以65举个栗子)

    • 第二步: 我们通过算法: 将所有小于65的数字放在65的左边, 将所有大于65的数字放在65的右边.

    • 第三步: 递归的处理左边的数据.(比如你选择31来处理左侧), 递归的处理右边的数据.(比如选择75来处理右侧, 当然选择81可能更合适)

    • 最终: 排序完成

  • 和冒泡排序不同的是什么呢?

    • 我们选择的65可以一次性将它放在最正确的位置, 之后不需要任何移动.

    • 需要从开始位置两个两个比较, 如果第一个就是最大值, 它需要一直向后移动, 直到走到最后.

    • 也就是即使已经找到了最大值, 也需要不断继续移动最大值. 而快速排序对数字的定位是一次性的.

代码实现:

  var arr = [5, 4, 2, 14, 7, 3, 9]

         function quicksort(arr){
            //如果数组只只有一个或者为空就不用排序
            if (arr.length<=1) {
                return arr
            } else {
                // 找出数组中间的那个数,如果是偶数位时取前一位
                let middle=Math.floor(arr.length/2)
                //将这一位移除
              let newarr = arr.splice(middle,1)
                // console.log(newarr);
                let arrleft=[]//用于接收小于middle位值得数
                let arrright=[]//用于接收大于middle位值得数

                arr.forEach(el => {
                    if (el 

 

归并排序

基本思想与过程:先递归的分解数列,再合并数列(分治思想的典型应用)

(1)将一个数组拆成A、B两个小组,两个小组继续拆,直到每个小组只有一个元素为止。

(2)按照拆分过程逐步合并小组,由于各小组初始只有一个元素,可以看做小组内部是有序的,合并小组可以被看做是合并两个有序数组的过程。

(3)对左右两个小数列重复第二步,直至各区间只有1个数。

代码实现:

 var arr = [5, 4, 2, 14, 7, 3, 9]
         //拆分
        function divide(arr){
            //如果数组长度小于1就不要拆分了,因为一个数据默认就是有序得
            if (arr.length<=1) {
                return arr
            } else {
                let middle=Math.floor(arr.length/2)
                let arrleft=arr.slice(0,middle)
                // console.log(arrleft);
                let arrright=arr.slice(middle)
                // console.log(arrright);
                //合并并递归
                return hebing(divide(arrleft),divide(arrright))
            }

         }
         //合并
        function hebing(arrleft,arrright){
            let arr=[]
            while (arrleft.length>0 && arrright.length>0) {
                if (arrleft[0]

转载请注明:文章转载自 www.051e.com
本文地址:http://www.051e.com/it/1071880.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号