排序
快速排序
快速排序算法说下,基点怎么选?如果一个数组是已经排序好的怎么选基点?**
- 数组元素随机,取固定基准;
- 数组元素已排序或逆序,取随机基准;
- 更好的方法:三数取中,选取数组开头,中间和结尾的元素,通过比较,选择中间的值作为快排的基准。
优化
- 数组较小时选择插入排序
- 相同元素聚合
这里效率最好的快排组合 是:三数取中+插排+聚集相等元素,它和STL中的Sort函数效率差不多
聚集相同元素的话就是把相同的元素都聚集到中间,然后将左边和右边分开的时候可以减少一些元素。
//快速排序
function quickSort(arr){
//debugger;
let right = arr.length - 1
quick(arr,0,right)
console.log(arr)
}
function partition(arr,left,right){
if (left < right) {
midu(arr, left, right);
let pivot = right - 1;
//左指针
let i = left ;
//右指针
let j = right -1 ;
while (j > i) {
while (j > i && arr[i] < arr[pivot]) {i++}
while (j > i && arr[j] >= arr[pivot]) {j--}
if (i < j) {
swap(arr, i, j);
}else{
break;
}
}
if( i == j ) {swap(arr,i,pivot)}
return i;
}
}
function quick(arr,left,right){
if(left < right){
let i = partition(arr,left,right)
quick(arr, left, i - 1);
quick(arr, i + 1, right);
}
}
function midu(arr,left,right){
let mid = left+((right-left)>>1);// >> 优先级低于 + -
// 也可以写成let mid = Math.floor(left+right/2)
if (arr[left] > arr[mid]) {
swap(arr, left, mid);
}
if (arr[left] > arr[right]) {
swap(arr, left, right);
}
if (arr[right] < arr[mid]) {
swap(arr, right, mid);
}
swap(arr, right - 1, mid);
}
function swap(arr,a,b){
let temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
归并排序
//归并排序
function mergeSort(array){
debugger;
return mergeSortRec(array);
}
function mergeSortRec(array){
var length = array.length;
if(length === 1) {
return array; }
var mid = Math.floor(length / 2),
left = array.slice(0, mid),
right = array.slice(mid, length);
return merge(mergeSortRec(left), mergeSortRec(right));
}
function merge(left, right){
var result = [],
il = 0,
ir = 0;
while(il < left.length && ir < right.length) {
if(left[il] < right[ir]) {
result.push(left[il++]);
} else{
result.push(right[ir++]); // {10}
}
}
while (il < left.length){ // {11}
result.push(left[il++]);
}
while (ir < right.length){ // {12}
result.push(right[ir++]);
}
return result; // {13}
}
插入排序
//插入排序
function insertSort(arr) {
debugger;
for(let i = 1; i < arr.length; i++) {
let j, temp = arr[i];
for(j = i; j > 0 && arr[j - 1] > temp; j --) {
arr[j] = arr[j - 1];
}
arr[j] = temp;
}
}
优化
插入排序前面的元素是有序的,可以采用二分查找的方式
堆排序
function heapSort(array) {
//debugger;
var heapSize = array.length;
buildHeap(array); //{1}
while (heapSize > 1) {
heapSize--;
swap(array, 0, heapSize); //{2}
heapify(array, heapSize, 0); //{3}
}
console.log(array)
};
//建堆
function buildHeap(array){
var heapSize = array.length;
for (var i = Math.floor(array.length / 2); i >= 0; i--) {
heapify(array, heapSize, i);
}
};
//父节点和两个子节点的比较过程
function heapify(array, heapSize, i){
var left = i * 2 + 1,
right = i * 2 + 2,
largest = i;
if (left < heapSize && array[left] > array[largest]) {
largest = left;
}
if (right < heapSize && array[right] > array[largest]) {
largest = right;
}
if (largest !== i) {
swap(array, i, largest);
heapify(array, heapSize, largest);
}
};
选择排序
function selectionSort(arr) {
debugger;
// 选多少次
for(let i = 0; i < arr.length - 1; i ++) {
let minIndex = i;
// 在arr[i + 1, ] 中找最小值索引, i+1 代表有序的下一个数,我们默认第一个元素是最小的
for(let j = i + 1; j < arr.length; j ++) {
if(arr[j] < arr[minIndex]) {
minIndex = j;
}
}
if(minIndex != i) {
// 交换
let temp = arr[minIndex]
arr[minIndex] = arr[i]
arr[i] = temp;
}
}
}
优化
原来的选择排序是每次选择一个最小的值放在最前面
改进措施:每次循环找到最大值和最小值,然后最小值和第一个交换,最大值和最后一个交换
冒泡排序
优化
算法的稳定性:冒泡,快排,归并,基数是稳定的