JS十大排序算法实现

一.冒泡排序(Bubble Sort):

1.概念:

作为最简单的排序算法之一,冒泡排序还有一种优化算法,就是立一个flag,当在一趟序列遍历中元素没有发生交换,则证明该序列已经有序。

2.两种情况:

(1)最快情况:

当输入的数据已经是正序时

(2)最慢情况:

当输入的数据是反序时

3.冒泡排序JavaScript代码实现:

		function bubbleSort(arr) {
			 var len = arr.length;
		 for (var i = 0; i < len; i++) {
  			  for (var j = 0; j < len - 1 - i; j++) {
     			   if (arr[j] > arr[j+1]) {        //相邻元素两两对比
         				   var temp = arr[j+1];        //元素交换
           				   arr[j+1] = arr[j];
           				 arr[j] = temp;
       				 }
  				  }
		  }
		 return arr;
		}

二.选择排序:

1.概念:

在时间复杂度上表现最稳定的排序算法之一,因为无论什么数据进去都是O(n²)的时间复杂度,所以用到它的时候,数据规模越小越好。

唯一的好处可能就是不占用额外的内存空间

2.选择排序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;
		}

三.插入排序:

1.概念:

插入排序和冒泡排序一样,也有一种优化算法,叫做拆半插入。

2.插入排序JavaScript代码实现:

	function insertionSort(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;
	}

四.希尔排序:

1.概念:

希尔排序是插入排序的一种更高效率的实现。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序的核心在于间隔序列的设定。既可以提前设定好间隔序列,也可以动态的定义间隔序列。

2.希尔排序JavaScript代码实现:

		function shellSort(arr) {
				var len = arr.length,
 				   temp,
  				  gap = 1;
			 while(gap < len/3) {          //动态定义间隔序列
  				  gap =gap*3+1;
			 }
		 for (gap; gap> 0; gap = Math.floor(gap/3)) {
  			  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;
  			  }
			 }	
		return arr;
		}

五.归并排序:

1.概念:

(1)作为一种典型的分而治之思想的算法应用,归并排序的实现由两种方法:

自上而下的递归(所有递归的方法都可以用迭代重写)

自下而上的迭代

(2)简而言之,就是JavaScript没有对递归进行优化。运用递归函数不仅没有运行速度上的优势,还可能造成程序运行失败。因此不建议使用递归。

(3)和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(n log n)的时间复杂度。代价是需要额外的内存空间。

2.归并排序JavaScript代码实现:

function mergeSort(arr) {  //采用自上而下的递归方法
var len = arr.length;
if(len < 2) {
    return arr;
}
var middle = Math.floor(len / 2),
    left = arr.slice(0, middle),
    right = arr.slice(middle);
return merge(mergeSort(left), mergeSort(right));
}

function merge(left, right)
{
var result = [];

while (left.length>0 && right.length>0) {
    if (left[0] <= right[0]) {
        result.push(left.shift());
    } else {
        result.push(right.shift());
    }
}

while (left.length)
    result.push(left.shift());

while (right.length)
    result.push(right.shift());

return result;
}

六.快速排序:

1.概念:

(1)又是一种分而治之思想在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。

(2) 它是处理大数据最快的排序算法之一了。虽然Worst Case的时间复杂度达到了O(n²),在大多数情况下都比平均时间复杂度为O(n log n) 的排序算法表现要更好

(3)快速排序的最坏运行情况是O(n²),比如说顺序数列的快排。但它的平摊期望时间是O(n log n) ,且O(n log n)记号中隐含的常数因子很小,比复杂度稳定等于O(n log n)的归并排序要小很多。所以,对绝大多数顺序性较弱的随机数列而言,快速排序总是优于归并排序。

2.快速排序JavaScript代码实现:

function quickSort(arr, left, right) {
var len = arr.length,
    partitionIndex,
    left = typeof left != 'number' ? 0 : left,
    right = typeof right != 'number' ? len - 1 : right;

if (left < right) {
    partitionIndex = partition(arr, left, right);
    quickSort(arr, left, partitionIndex-1);
    quickSort(arr, partitionIndex+1, right);
}
return arr;
}

function partition(arr, left ,right) {     //分区操作
var pivot = left,                      //设定基准值(pivot)
    index = pivot + 1;
for (var i = index; i <= right; i++) {
    if (arr[i] < arr[pivot]) {
        swap(arr, i, index);
        index++;
    }        
}
swap(arr, pivot, index - 1);
return index-1;
}

function swap(arr, i, j) {
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}

七.堆排序:

1.概念:

堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:

大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列

小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列

2.堆排序JavaScript代码实现:

var len;    //因为声明的多个函数都需要数据长度,所以把len设置成为全局变量

function buildMaxHeap(arr) {   //建立大顶堆
len = arr.length;
for (var i = Math.floor(len/2); i &gt;= 0; i--) {
    heapify(arr, i);
}
}

function heapify(arr, i) {     //堆调整
var left = 2 * i + 1,
    right = 2 * i + 2,
    largest = i;

if (left < len && arr[left] > arr[largest]) {
    largest = left;
}

if (right < len && arr[right] > arr[largest]) {
    largest = right;
}

if (largest != i) {
    swap(arr, i, largest);
    heapify(arr, largest);
}

}

function swap(arr, i, j) {
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}

function heapSort(arr) {
buildMaxHeap(arr);

for (var i = arr.length-1; i > 0; i--) {
    swap(arr, 0, i);
    len--;
    heapify(arr, 0);
}
return arr;
}

八.计数排序:

1.概念:

计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。

作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。

2.计数排序JavaScript代码实现:

function countingSort(arr, maxValue) {
var bucket = new Array(maxValue+1),
    sortedIndex = 0;
    arrLen = arr.length,
    bucketLen = maxValue + 1;

for (var i = 0; i < arrLen; i++) {
    if (!bucket[arr[i]]) {
        bucket[arr[i]] = 0;
    }
    bucket[arr[i]]++;
}

for (var j = 0; j < bucketLen; j++) {
    while(bucket[j] > 0) {
        arr[sortedIndex++] = j;
        bucket[j]--;
    }
}

return arr;
}

九.桶排序:

1.概念:

(1)桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。

(2)为了使桶排序更加高效,我们需要做到这两点:

在额外空间充足的情况下,尽量增大桶的数量

使用的映射函数能够将输入的N个数据均匀的分配到K个桶中

同时,对于桶中元素的排序,选择何种比较排序算法对于性能的影响至关重要。

2.不同情况:

(1)最快情况:

当输入的数据可以均匀的分配到每一个桶中

(2)最慢情况:

当输入的数据被分配到了同一个桶中

3.桶排序JavaScript代码实现:

function bucketSort(arr, bucketSize) {
if (arr.length === 0) {
  return arr;
}

var i;
var minValue = arr[0];
var maxValue = arr[0];
for (i = 1; i < arr.length; i++) {
  if (arr[i] < minValue) {
      minValue = arr[i];                //输入数据的最小值
  } else if (arr[i] > maxValue) {
      maxValue = arr[i];                //输入数据的最大值
  }
}

//桶的初始化
var DEFAULT_BUCKET_SIZE = 5;            //设置桶的默认数量为5
bucketSize = bucketSize || DEFAULT_BUCKET_SIZE;
var bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1;   
var buckets = new Array(bucketCount);
for (i = 0; i < buckets.length; i++) {
    buckets[i] = [];
}

//利用映射函数将数据分配到各个桶中
for (i = 0; i < arr.length; i++) {
    buckets[Math.floor((arr[i] - minValue) / bucketSize)].push(arr[i]);
}

arr.length = 0;
for (i = 0; i < buckets.length; i++) {
    insertionSort(buckets[i]);                      //对每个桶进行排序,这里使用了插入排序
    for (var j = 0; j < buckets[i].length; j++) {
        arr.push(buckets[i][j]);                      
    }
}

return arr;
}

十.基数排序:

1.概念:

(1)基数排序有两种方法:
MSD 从高位开始进行排序
LSD 从低位开始进行排序
基数排序 vs 计数排序 vs 桶排序

(2)这三种排序算法都利用了桶的概念,但对桶的使用方法上有明显差异:
基数排序:根据键值的每位数字来分配桶
计数排序:每个桶只存储单一键值
桶排序:每个桶存储一定范围的数值

2.基数排序JavaScript代码实现:

//LSD Radix Sort
var counter = [];
function radixSort(arr, maxDigit) {
var mod = 10;
var dev = 1;
for (var i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) {
    for(var j = 0; j < arr.length; j++) {
        var bucket = parseInt((arr[j] % mod) / dev);
        if(counter[bucket]==null) {
            counter[bucket] = [];
        }
        counter[bucket].push(arr[j]);
    }
    var pos = 0;
    for(var j = 0; j < counter.length; j++) {
        var value = null;
        if(counter[j]!=null) {
            while ((value = counter[j].shift()) != null) {
                  arr[pos++] = value;
            }
      }
    }
}
return arr;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值