Algorithm — 排序

这篇博客详细介绍了五种经典的排序算法:冒泡排序,快速排序,归并排序,插入排序和希尔排序。包括它们的排序原理和代码实现。冒泡排序通过不断交换相邻元素实现排序;快速排序通过选取基准值并分割序列来排序;归并排序采用合并有序子序列的方法;插入排序通过将元素插入到已排序的子序列中实现;希尔排序则利用增量序列进行分组排序。每个算法都附带了运行结果展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、冒泡排序
1、排序原理
①从第一个元素开始,把当前元素和下一个索引的元素比较,如果当前元素大于下一个元素,则把当前元素和下一个元素互换位置,以此类推,直到比较到最后一个元素,此时,最后一个元素就是数组中的最大的元素。
②循环①中的排序流程,但要注意的是第一轮排序之后,最后一个元素已经是最大的,所以第二轮排序时只用排序到第length-1个元素。
③下一轮重复②中的操作,排序最后位置依次减1.
2、代码实现

//元素交换位置
function swap(arr, left, right) {
    let mid_value = arr[left]
    arr[left] = arr[right]
    arr[right] = mid_value
}
function bubble(arr) {
  	for(let j = arr.length-1; j>0; j--){
 		for(let i=0; i<j; i++){
           if(arr[i]>arr[i+1]){
           swap(arr, i, i+1)
         	}
       	}
   	}
  return arr
}

运行结果:

在这里插入图片描述

二、快速排序
1、排序原理
①选取系列中的第一个元素作为基准值,并存入变脸x中;
②从待排序序列右侧扫描,把小于基准值的元素移动到序列左侧;
③从待排序序列左侧扫描,把大于基准值的元素移到序列右侧;
④把变量x中的值插入分界处,到此就完成了一趟快排;
⑤通过第一趟快排后,序列就被划分成了两个子表,且基准值左侧的元素均小于基准值,右侧的元素均大于基准值。
⑥分别对左子表和右子表继续按上述①-⑤规则继续进行分割,直到所有子表长度不超过1为止,此时也就完成了快速排序。
代码实现:

let arr=[8,9,5,6,2,7,10,15,19]
function quickPass(arr, low, high) {
  let x,i=1
  x=arr[low]
  while(low<high){
    while(low<high &&arr[high]>x){
       high--
    }
    if(low<high){
       arr[low]=arr[high]
       low++
    }
    while(low<high && arr[low]<x){
       low++
    }
    if(low<high) {
       arr[high]=arr[low]
       high--
     }
   i++
  }
arr[low]=x 
return low
}
function quickSort(arr, low, high){
  if(low<high){
     let pos = quickPass(arr, low, high)
     quickSort(arr, low, pos-1)
     quickSort(arr, pos+1, high)
  }
return arr
}

运行结果:
在这里插入图片描述
三、归并排序

基本思想: 归并排序是基于合并,将两个或两个以上有序表合并成一个新的有序表。

排序原理:假设初始序列有n个记录。①将n个记录看成n个有序的子序列,每个子序列的长度为1。②然后两两归并,当n为偶数时,得到n/2个长度为2的有序子序列,当n为奇数时,得到floor(n/2)个长度为2的有序子序列加1个长度为1的子序列。③在此基础上,再对长度为2的有序子序列进行两两归并,得到若干长度为4的有序子序列。如此重复,直到得到一个长度为n的有序序列为止。

代码实现:

	function merge(left, right){  
        var result=[];
        while(left.length>0 && right.length>0){
            if(left[0]<right[0]){
            /*shift()方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。*/
                result.push(left.shift());
            }else{
                result.push(right.shift());
            }
        }
        return result.concat(left).concat(right);
   	 }
   	 
    function mergeSort(items){
        if(items.length == 1){
           	 return items;
    		}
     var middle = Math.floor(items.length/2),
        left = items.slice(0, middle),
        right = items.slice(middle);
        return merge(mergeSort(left), mergeSort(right));
   }

运行结果:
在这里插入图片描述
四、插入排序

基本思想:在一个已排好序的记录子集的基础上,每一步将下一个待排序的记录有序插入到已排好序的记录子集中,直到将所有待排记录全部插入为止。例如,打扑克牌时的抓牌就是插入排序的一个很好的例子,每抓一张牌,插入到合适位置,直到抓完牌为止,即可得到一个有序序列。

排序过程:①将第i个(从第一个开始)记录视为已排好序的单元素子集盒。②将第i+1个记录存入辅助变量x中(视为待排序记录)。③将x与前面的记录顺次比较,将所有大于x的记录依次向后移动一个位置,直到遇到一个小于或者等于x的记录,此时此记录后面的位置为空,则将x插入此位置,到此就完成了一个待排记录的插入排序。④循环上述②-③,直到所有待排记录全部插入为止。

代码实现:

let x, j
function insSort(arr) {
  for(let i=0;i<arr.length-1;i++){
     x= arr[i+1]
     j =i 
     while(x<arr[j]) {
       arr[j+1]=arr[j]
       j--
     }
    arr[j+1] = x
  }
return arr
}

运行结果:
在这里插入图片描述

五、希尔排序

基本思想:先将待排序记录序列以增量(一般初次取序列的一半,以后每次减半,直到为1)为间隔,分割成若干个“较稀疏的”子序列,分别进行直接插入排序。经过对分组的排序,整个序列中的记录已经基本有序,最后再对全部记录进行一次直接插入排序。

排序过程:①取序列的一半(Math.floor(n/2))为增量d1。②把所有索引相隔d1的记录放一组,组内进行直接插入排序。③取d1的一半(Math.floor(d1/2))为增量d2,重复上述②中的步骤。④重复上述②-③步骤,直到增量为,即所有记录放同一组里。⑤最后对这组记录进行直接插入排序,即可完成序列的希尔排序。

代码实现:

function shellSort(arr) {
   let len = arr.length
   for(let d=Math.floor(len/2); d>0; d=Math.floor(d/2)) {
      for(let i=d; i<len; i++) {
           for(let j=i-d; j>=0&&arr[j]>arr[j+d]; j-=d) {
                let temp = arr[j]
                arr[j] = arr[d+j]
                arr[d+j] = temp 
                 
             }
        }   
    }
 return arr
}

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值