常用八大排序算法
前言
- 此篇来介绍常用的排序算法JavaScript版实现,Java版请戳这里【含简略讲解】。其实网上的介绍讲解汗牛充栋,并且有很多优秀的文章,写此篇的目的是为了加深下自己的印象,还有融入点自己的想法。当笔记使啦~
- 注:排序元素顺序以从小到大排序为主;
var arr = [7,4,5,3,6,2,1,9,0];
var arr1 = new Array(100000);
for(let i=0;i<100000;i++){
arr1[i] = Math.floor((Math.random()*100000));
}
/**
* @see 冒泡排序,每次循环确定一个大的数/小的数放在数组的两端
*
*/
function bobbleSort(arr){
for(let i=0;i<arr.length;i++){ //控制循环次数
for(let j=0;j<arr.length-i-1;j++){
if(arr[j]>arr[j+1]) {
let temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
//console.log(arr);
}
/**
* @see 选择排序
* 注重索引的选择,每次选择最小/最大的那个数的索引,
* 然后再和数组的两端交换位置
*
*/
function selectSort(arr){
for(let i=0;i<arr.length-1;i++){
let minIndex = i;
for(let j=i+1;j<arr.length;j++){
if(arr[j]<arr[minIndex]){
minIndex = j;
}
}
let temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
/**
*
* @see 插入排序
*/
let arrIns = arr1.slice(0,arr1.length);
function insertSort(arr){
for(let i = 0;i<arr.length-1;i++){
//定义插入索引
let j = i+1;
//暂存需要插入的数字
let insertNum = arr[j];
while(j>=1 && insertNum < arr[j-1]){
arr[j] = arr[j-1];
j--;
}
arr[j] = insertNum;
}
}
/**
* @see 希尔排序,缩小增量的排序
*
*/
let arrShl = arr1.slice(0,arr1.length);
function ShellSort(arr){
//步长循环
for(let gep = parseInt(arr.length/2);gep > 0;gep=parseInt(gep/2)){
//分组式插入排序
for(let i = gep;i < arr.length;i++){
//定义插入索引
let j = i;
let insertNum = arr[j];
while(j >= 0 && insertNum < arr[j-gep]){
arr[j] = arr[j-gep];
j -= gep;
}
arr[j] = insertNum;
}
}
}
/**
* @see 此类用于演示归并排序
*
* */
class MergeSort{
//分治合并总方法
mergeSort(arr,left,right,temp){
if(left<right){
let mid = parseInt((left+right)/2);
this.mergeSort(arr,left,mid,temp); //向左递归分解
this.mergeSort(arr,mid+1,right,temp); //向右递归分解
this.merge(arr,left,mid,right,temp);
}
}
/**
* @param arr 需要排序的目标数组
* @param left 左边有序序列的初始索引
* @param mid 中间索引
* @param right 右边索引
* @param temp 中间临时数组
* */
merge(arr,left,mid,right,temp) {
//左边有序数组起始索引
let i = left;
//右边数组起始索引
let j = mid+1;
//临时数组起始索引
let t = 0;
//循环进行归并
while(i <= mid && j <= right){
if(arr[i]<=arr[j]) {
temp[t] = arr[i];
i++;
t++;
}else{
temp[t] = arr[j];
j++;
t++;
}
}
//左边数组剩余元素
while(i<=mid){
temp[t] = arr[i];
i++;
t++;
}
//右边数组剩余元素
while(j<=right){
temp[t] = arr[j];
j++;
t++;
}
//将临时数组copy到原数组
//注意不是每次都copy所有元素到元素组
t = 0;
let tempLeft = left;
while(tempLeft <= right){
arr[tempLeft] = temp[t];
t+=1;
tempLeft+=1;
}
}
}
/**
* @see 快速排序
* @param arrQ 目标数组
* @param left 逻辑数组的起始索引
* @param right 逻辑数组的终止索引
*/
function quickSort(arrQ,left,right){
if(left>=right){
return;
}
//寻找一个基数
let key = arr[left];
//构造两个指针
let i = left,j=right;
while(i<j){
while(arr[j]>=key && i<j){
j--;
}
while(arr[i]<=key && i<j){
i++;
}
//交换位置
let temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
arr[left] = arr[i];
arr[i] = key;
quickSort(arrQ,left,i-1);
quickSort(arrQ,i+1,right);
}
/**
* @param arr 目标数组
* @param i 逻辑二叉树的头节点
* @param length 数组的长度
*/
function adjustHeap(arr,i,length){
//取出当前节点值
let temp = arr[i];
//调整2*k+1,是i的左子节点
for(let k = 2*i+1;k<length;k=k*2+1){
if(k+1 < length && arr[k] < arr[k+1]){ //说明右子节点的数大于左子节点的数字
k++;
}
//赋值给头节点
if(arr[k] > temp){
arr[i] = arr[k];
i = k;
}else{
break;
}
}
//当for循环结束后,我们已经将以 i 为父节点的树最大值,放在了最顶(局部)
arr[i] = temp;
}
/**
* @see 堆排序
* @param arr 目标数组
*/
function heapSort(arr){
let temp = 0;
//构建堆顶结构
for(let i = parseInt(arr.length/2)-1;i>=0;i--){
adjustHeap(arr,i,arr.length);
}
//将最大元素“沉底”
for(let j = arr.length-1;j>0;j--){
//交换
temp = arr[j];
arr[j] = arr[0];
arr[0] = temp;
adjustHeap(arr,0,j);
}
}
//测试冒泡排序
// console.time("bobble");
// bobbleSort(arr);
// console.timeEnd("bobble");
//测试选择排序
//let arrSel = arr1.slice(0,arr1.length);
//console.time("selectSort");
//selectSort(arrSel);
//console.timeEnd("selectSort");
//测试插入排序
//let arrIns = arr1.slice(0,arr1.length);
//console.time("insertSort");
//insertSort(arrIns);
//console.timeEnd("insertSort");
//测试希尔排序
//let arrShell = arr1.slice(0,arr1.length);
//console.time("shellSort");
//ShellSort(arrShell);
//console.timeEnd("shellSort");
//测试归并排序
// function mergeSortTest(arr) {
// let right = arr.length-1;
// let temp = new Array(right+1).fill(0);
// let test = new MergeSort();
// test.mergeSort(arr,0,right,temp);
// }
// mergeSortTest(arr);
//测试快速排序
//quickSort(arr,0,arr.length-1);
//console.log(arr);
//测试堆排序
// heapSort(arr);
// console.log(arr);