数据结构标准入门-5种常见排序算法

192 阅读3分钟

在我们的程序中,排序是非常常见的一种需求,提供一些数据元素,把这些数据元素按照一定的规则进 行排序。比如查询一些订单,按照订单的日期进行排序;再比如查询一些商品,按照商品的价格进行排 序等等。所以,接下来我们要学习一些常见的排序算法。

冒泡排序

冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。

实现原理

  • 比较相邻的元素。如果前一个元素比后一个元素大,就交换这两个元素的位置。
  • 对每一对相邻元素做同样的工作,从开始第一对元素到结尾的最后一对元素。最终最后位置的元素 就是最大值。

代码实现

// 冒泡排序
// 1. 比对相邻的两个元素,如果前面一个元素比后面一个元素大
// 2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对元素,最终位置的元素就是最大值
function Bubble(arr){
    for(let i=arr.length;i>0;i--){
        for(let j=0;j<i;j++){
            if(greater(arr[j],arr[j+1])){
                [arr[j],arr[j+1]]=[arr[j+1],arr[j]]
            }
        }
    }
    function greater(v,w){
        return v>w
    }
    return arr
}
console.log(Bubble([9,8,7,6]))

选择排序

选择排序是一种更加简单直观的排序方法。

实现原理

  • 每一次遍历的过程中,都假定第一个索引处的元素是最小值,和其他索引处的值依次进行比较,如 果当前索引处的值大于其他某个索引处的值,则假定其他某个索引出的值为最小值,最后可以找到 最小值所在的索引
  • 交换第一个索引处和最小值所在的索引处的值

代码实现

function Selection(arr){
    for(let i=0;i<arr.length;i++){
        for(let j=0;j<arr.length;j++){
            if(arr[j]>arr[i]){
                [arr[j],arr[i]]=[arr[i],arr[j]]
            }
        }
    }
    return arr
}
console.log(Selection([9,8,7,6,5,4]))

插入排序

插入排序(Insertion sort)是一种简单直观且稳定的排序算法。

插入排序的工作方式非常像人们排序一手扑克牌一样。开始时,我们的左手为空并且桌子上的牌面朝 下。然后,我们每次从桌子上拿走一张牌并将它插入左手中正确的位置。为了找到一张牌的正确位置, 我们从右到左将它与已在手中的每张牌进行比较

实现原理

  • 把所有的元素分为两组,已经排序的和未排序的;
  • 找到未排序的组中的第一个元素,向已经排序的组中进行插入;
  • 倒叙遍历已经排序的元素,依次和待插入的元素进行比较,直到找到一个元素小于等于待插入元素, 那么就把待插入元素放到这个位置,其他的元素向后移动一位

代码实现

function Insertion(arr){
    for(let i=1;i<arr.length;i++){
        for(let j=i;j>0;j--){
            if(arr[j]<arr[j-1]){
                [arr[j],arr[j-1]]=[arr[j-1],arr[j]]
            }
        }
    }
    return arr
}
console.log(Insertion([9,8,7,6,5,4]))

希尔排序

希尔排序是插入排序的一种,又称“缩小增量排序”,是插入排序算法的一种更高效的改进版本。

实现原理

  • 选定一个增长量h,按照增长量h作为数据分组的依据,对数据进行分组;
  • 对分好组的每一组数据完成插入排序;
  • 减小增长量,最小减为1,重复第二步操作。

代码实现

function shellSort(arr) {
    let len = arr.length;
    // gap 即为增量
    for (let gap = Math.floor(len / 2); gap > 0; gap = Math.floor(gap / 2)) {
        for (let i = gap; i < len; i++) {
            let current = arr[i];
            while(i-gap>=0&&current < arr[i - gap]) {
                arr[i] = arr[i - gap];
                i = i - gap;
            }
            arr[i] = current;
        }
    }
    return arr
}

console.log(shellSort([9,8,7,6,1]))

归并排序

归并排序是建立在递归操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将 已有序的子 序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个 有序表合并成一个有序 表,称为二路归并。

排序原理

  • 尽可能的一组数据拆分成两个元素相等的子组,并对每一个子组继续拆分,直到拆分后的每个子组 的元素个数是1为止。
  • 将相邻的两个子组进行合并成一个有序的大组
  • 不断的重复步骤2,直到最终只有一个组为止

代码实现

function Merge(arr){
    let assets=new Array(arr.length)
    let lo=0
    let hi=arr.length-1
    function sort(a,lo,hi){
        if(hi<=lo){
            return
        }
        let mid=Math.floor((hi+lo)/2)
        sort(a,lo,mid)
        sort(a,mid+1,hi)
        merge(a,lo,mid,hi)
    }
    function merge(a,lo,mid,hi){
        let i=lo
        let p1=lo
        let p2=mid+1
        while (p1<=mid&&p2<=hi){
            if(a[p1]<a[p2]){
                assets[i++]=a[p1++]
            }else {
                assets[i++]=a[p2++]
            }
        }
        while(p1<=mid){
            assets[i++]=a[p1++]
        }
        while (p2<=hi){
            assets[i++]=a[p2++]
        }
        for(let j=lo;j<=hi;j++){
            a[j]=assets[j]
        }
    }
    sort(arr,lo,hi)
    return arr
}
console.log(Merge([9,8,7,6,5]))

快速排序

快速排序是对冒泡排序的一种改进。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部 分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进 行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

排序原理

  • 首先设定一个分界值,通过该分界值将数组分成左右两部分;
  • 将大于或等于分界值的数据放到到数组右边,小于分界值的数据放到数组的左边。此时左边部分中 各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值;
  • 然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数 据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处 理。
  • 重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部 分的顺序。当左侧和右侧两个部分的数据排完序后,整个数组的排序也就完成了。

切分原理

把一个数组切分成两个子数组的基本思想:

  • 找一个基准值,用两个指针分别指向数组的头部和尾部;
  • 先从尾部向头部开始搜索一个比基准值小的元素,搜索到即停止,并记录指针的位置;
  • 再从头部向尾部开始搜索一个比基准值大的元素,搜索到即停止,并记录指针的位置;
  • 交换当前左边指针位置和右边指针位置的元素
  • 重复2,3,4步骤,直到左边指针的值大于右边指针的值停止。

代码实现

function Quick(arr){
    let lo=0
    let hi=arr.length-1
    function sort(arr,lo,hi){
        if(hi<lo){
            return
        }
        let p=partition(arr,lo,hi)
        sort(arr,lo,p-1)
        sort(arr,p+1,hi)
    }
    function partition(arr,lo,hi){
        let key=arr[lo]
        let left=lo
        let right=hi+1
        while(true){
            while (key<arr[--right]){
                if(right==lo){
                    break
                }
            }
            while (arr[++left]<key){
                if(left==hi){
                    break
                }
            }
            if(left>=right){
                break
            }else{
                [arr[left],arr[right]]=[arr[right],arr[left]]
            }
        }
        [arr[lo],arr[right]]=[arr[right],arr[lo]]
        return right
    }
    sort(arr,lo,hi)
    return arr
}
console.log(Quick([9,8,7,6,5]))

以上,感谢观看,如果有帮助的话可以点赞收藏关注下专栏哦 持续更新更多数据结构和算法代码片段。希望能够帮助到更多人