目录
一、选择排序
二、冒泡排序
三、插入排序
1. 希尔排序
四、归并排序
五、快速排序
版权声明:本文为博主原创文章,若文章中有错误请联系博主改正,请不要恶意留言(不喜欢请绕道)。欢迎大家转载,转载时请注明原文地址:https://blog.csdn.net/qq_37674616/article/details/82315651
目录
一、选择排序
二、冒泡排序
三、插入排序
1. 希尔排序
四、快速排序
我们衡量一个算法的指标包括:
时间复杂度 (在排序过程中需要比较和交换的次数)
空间复杂度 (在排序过程中需要的辅助存储空间)
稳定性 (该算法的实现是否可以保证排序后相等元素的初始顺序,只要该算法存在一种实现可以保证这种特征,那么该算法就是稳定的)
内部排序/外部排序 (在排序过程中数据元素是否完全在内存)
下表为各排序算法的性能标准:
工作原理:初始时在未排序序列中找最小(最大)元素,放到序列的起始位置作为已排序序列;然后再从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾。以此类推。知道所有元素均排序完毕。
/**
* @Author cc
* @DateTime 2018-09-01
* @param {arr} 未排序数组
* @return {arr} 已排序数组
* @description 选择排序
*/
function sort(arr){
var len=arr.length;
//已排序序列的末尾
for(var i=0;i
/**
* @Author cc
* @DateTime 2020-05-07
* @param {nums} 未排序数组
* @return {nums} 已排序数组
* @description 选择排序
*/
function insertionSort (nums) {
for(let i=1;i
该排序算法不稳定,最差时间复杂度 o(n^2);最优时间复杂度 o(n^2);平均时间复杂度 o(n^2)
冒泡排序是一种简单的排序算法,它重复走访要排序的数列,一次比较两个元素,如果他们的的顺序错误就把他们调换过来,知道没有元素再需要交换,排序完成。
算法描述如下:
比较相邻的元素。如果第一个比第二个大,就交换他们;
对于每个相邻的元素重复相同的工作,知道最后一个元素,这样最后的元素会是最大的数
针对所有元素重复以上的步骤,除了最后一个元素
重复上面1~3步骤,知道排序结束
算法实现:
/**
* @Author cc
* @DateTime 2018-08-31
* @param {arr} 待数组
* @return {arr} 排好序的数组
* @description 这是一个冒泡排序算法
*/
function bubbleSort(arr) {
var len = arr.length;
for (var i = 0; i < len - 1; i++) { //比较的趟数,每次将最大值放到数组最后
for (var j = 0; j < len - i - 1; j++) { //将相邻的两个元素,两两比较
if (arr[j]>arr[j+1]) { //元素交换值
var temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
return arr;
}
var arr=[1,3,5,12,14,8,99];
var result=bubbleSort(arr);
console.log(result); //[1, 3, 5, 8, 12, 14, 99]
辅助草图:
冒泡排序是稳定的排序算法,它的最差时间复杂度 o(n^2)即已排序数组;平均时间复杂度o(n^2),最优时间复杂度o(n)即在内部循环第一次运行时,使用一个旗标来表示该数组是不是已经是最小的了。
将上面代码做如下改动
/**
* @Author cc
* @DateTime 2020-05-07
* @param {nums} 未排序数组
* @return {nums} 已排序数组
* @description 冒泡排序
*/
function bubbleSort(nums) {
do {
var swapped = false;
for (var i = 0; i < nums.length; i++) {
if (nums[i] > nums[i+1]) {
var temp = nums[i];
nums[i] = nums[i+1];
nums[i+1] = temp;
swapped = true;
}
}
} while(swapped);
}
草图如下所示:
工作原理:是通过构建有序序列,对未排序数组,在已排序序列中从后向前扫描,找到相应位置并插入。
算法描述:
1. 从第一元素开始,该元素可以默认已经被排序
2. 取出下一个元素,在已经排序序列中从后向前扫描
3. 如果已排序的元素大于新元素,将该元素移到下一个位置
4.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
5.将新元素插入到该位置
6.重复2~5
/**
* @Author cc
* @DateTime 2018-09-01
* @param {arr} 待排序序列
* @return {arr} 排好序序列
* @description 插入排序
*/
function insertSort(arr) {
var len = arr.length;
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;
}
var arr=[8, 3, 5, 9, , 7, 1, 2 ];
var result=insertSort(arr); //从小到大排序
console.log(result); //[1, 2, 3, 4, 5, 6, 7, 8]
插入排序稳定,最差时间复杂度o(n^2)待排序列是降序序列;最优时间复杂度o(n)即待排序列是升序
平均时间复杂度o(n^2)
希尔排序: 是对插入排序的改进,它与插入不同之处它会优先比较距离较远的元素
算法描述:
选择一个增量序列 t1,t2,...tk,其中ti>tj,tk=1;
按增量序列个数k,对序列进行k趟排序
每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m的子序列,分别对各自表进行直接插入排序.当增量因子为一时,整个序列被分为一组,算法终止。
/**
* @Author cc
* @DateTime 2018-09-01
* @param {arr}
* @return {arr} 已排序数组
* @description 希尔排序
*/
function ShellSort(arr) {
var len = arr.length;
var temp, gap = 1;
while (gap <= len / 3) {
gap = gap * 3 + 1; //生成增量
}
while (gap >= 1) { //当分组变成成1时则排序完成
for (var i = gap; i < len; i++) { //按增量循环数组
temp = arr[i];
//增量大于零且前面的数组的值大于后面数组的值则交换位置
for (var j = i - gap; j >= 0 && arr[j] > temp; j -= gap) {
arr[j + gap] = arr[j];
}
arr[j + gap] = temp;
}
console.log(gap);
gap = (gap - 1) / 3; //递减增量
}
return arr;
}
var arr = [5, 9, 2, 4,1,2,8,3,9,1];
var result = ShellSort(arr);
console.log(result);
下图为增量为4时的内部数据交换图:
希尔排序稳定,时间复杂度为o(n^2),最优时间复杂度o(n)
算法描述:
指的是将两个已经排序的序列合并成一个序列的操作。归并排序算法依赖归并操作。
算法思想:
采用分支法,递归地把当前序列平均分割成两半,然后再保证左右顺序情况下合并在一起。
/**
* @Author cc
* @DateTime 2020-05-07
* @param {nums} 未排序数组
* @return {nums} 已排序数组
* @description 归并排序
*/
function mergeSort(nums){
if(nums.length<2) return nums;
const middle=Math.floor(nums.length/2);
const left=nums.slice(0,middle);
const right=nums.slice(middle);
return merge(mergeSort(left),mergeSort(right))
}
const merge=(left,right)=>{
const result=[]
while(left.length&&right.length){
if(left[0]>right[0]){
result.push(right.shift())
}else{
result.push(left.shift())
}
}
return result.concat(left,right);
}
该方法的基本思想:
1. 从数列中取出一个数作为基数。
2. 重新排序数列,所有元素比基准值小的放到基准值前,所有元素比基准值大的放到其后。
3. 在对基准值左右区间,重复第二步,直到个区间只有一个数
算法实现:
/**
* @Author cc
* @DateTime 2018-09-02
* @param arr 待排序数组
* @param left 数组第一个元素下标(0)
* @param right 数组最后一个元素下标
* @return arr 排好序的数组
*/
function quickSort(arr,left,right){
if(left=x){
j--;
}
if(i
下图为上面算的内部数据描述:
/**
* @Author cc
* @DateTime 2020-05-08
* @param {nums} 未排序数组
* @return {nums} 已排序数组
* @description 快速排序
*/
function quickSort(nums){
if(nums.length<2) return nums;
const pivot=nums[nums.length-1];
const left=[];
const right=[];
for(let i=0;i