排序算法
梳理下之前学习的排序算法
1. 冒泡排序
重复比较相邻元素,将大元素放在右边(小元素在左边,冒泡)
-
从左边开始。依次比较相邻元素大小,如果左边的元素大,则交换元素。(将最大元素置后)
-
重复步骤 1
n-1(数组长度-1)次。(因为大元素已经置后,所以在重复时可以不需要在比较后排元素)
function bubbleSort(arr) {
for (let i = 0, len = arr.length; i < len - 1; i++) {
for (let j = 0; j < len - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
const temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
2. 选择排序
重复遍历数组,依次标记最小元素位置置前
-
遍历数组,标记当前最小元素位置
-
交换第一个元素和最小元素位置
-
重复步骤
1~2,依次找出最小元素
function selectionSort(arr) {
for (let i = 0, len = arr.length; i < len - 1; i++) {
let min = i;
for (let j = i + 1; j < len; j++) {
if (arr[min] > arr[j]) {
min = j;
}
}
const temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
}
3. 插入排序
-
从左边第二个元素开始,依次和前面所有元素比较
-
如果元素比前面元素小,则交换元素
-
重复步骤
2,直到前面无元素或者比前面元素大
function insertionSort(arr) {
for (let i = 1, len = arr.length; i < len; i++) {
for (let j = i; j > 0; j--) {
if (arr[j] < arr[j - 1]) {
const temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp;
} else {
break;
}
}
}
}
4. 希尔排序
插入排序的改进,将插入排序的与前面元素比较改为与间隔元素比较
-
从左边第
n个元素开始,依次比较间隔为n的元素 -
如果元素比前面元素小,则交换元素
-
不断减小
n的值,直到为1,重复步骤1~2
function shellSort(arr) {
for (let gap = Math.floor(arr.length / 2); gap > 0; gap = Math.floor(gap / 2)) {
for (let i = gap, len = arr.length; i < len; i++) {
for (let j = i; j > 0; j = j - gap) {
if (arr[j] < arr[j - gap]) {
const temp = arr[j];
arr[j] = arr[j - gap];
arr[j - gap] = temp;
} else {
break;
}
}
}
}
}
5. 归并排序
归并排序的核心思想是分治
-
将数组等分两份
n / 2,分别排序左右数组再合并,递归直到n < 2 -
合并时通过比较两个数组前端元素大小,再决定将哪个元素置前
-
重复步骤
1~2
function mergeSort(arr) {
const len = arr.length;
const merge = (left, right) => {
let result = [];
while(left.length || right.length) {
if (!left.length) {
result = result.concat(right);
break;
}
if (!right.length) {
result = result.concat(left);
break;
}
if (left[0] <= right[0]) {
result.push(left.shift())
}
if (left[0] > right[0]) {
result.push(right.shift())
}
}
return result;
}
if (len < 2) {
return arr;
}
const mid = Math.floor(len / 2);
const left = mergeSort(arr.slice(0, mid));
const right = mergeSort(arr.slice(mid));
return merge(left, right);
}
6. 快速排序
快速排序的核心思想是分治
-
选择基准
a[0],遍历其余元素,对元素和基准进行比较大小 -
将比基准大的值放在左边,比基准小的值放右边
-
对左边右边元素分别重复步骤
1~2
function quickSort(arr) {
if (arr.lenght < 2) {
return arr;
}
const base = arr[0];
let left = [];
let right = [];
for (let i = 1, len = arr.length; i < len; i++) {
const cur = arr[i];
if (cur <= base) {
left.push(cur);
} else {
right.push(cur);
}
}
if (left.length > 1) left = quickSort(left);
if (right.length > 1) right = quickSort(right);
return [...left, base, ...right];
}
7. 堆排序
堆排序的核心思想是构建二叉树(节点元素大于子元素)
忘记怎么创建二叉树了,留着以后补上
8. 计数排序
空间换时间的计数
-
遍历原始数组,将元素出现的次数存入计数数组,其中索引为元素值
-
遍历计数数组,重复取出存入的元素(根据计数)
function countingSort(arr) {
const countArr = [];
const sortedArr = [];
for (let i = 0, len = arr.length; i < len; i++) {
const cur = arr[i];
if (countArr[cur]) {
countArr[cur] += 1;
} else {
countArr[cur] = 1;
}
}
for (let i = 0, len = countArr.length; i < len; i++) {
while (countArr[i]) {
sortedArr.push(i);
countArr[i] -= 1;
}
}
return sortedArr;
}
9. 桶排序
设定一定数量得桶,将不同数据放置于不同得桶中分别排序再连接
-
将数据映射到不同得桶
-
桶内排序
-
将不同桶得数据连接即可
function bucketSort(arr, bucketSize) {
if (arr.length < 2) {
return arr;
}
const result = [];
const min = Math.min.apply(null, arr);
const max = Math.max.apply(null, arr);
bucketSize = bucketSize || 5;
const step = Math.floor((max - min) / bucketSize);
const buckets = [];
// 映射
for (let i = 0, len = arr.length; i < len; i++) {
const cur = arr[i];
const index = Math.floor(cur / step);
buckets[index] = buckets[index] || [];
buckets[index].push(cur);
}
for (let i = 0, len = buckets.length; i < len; i++) {
if (buckets[i]) {
insertionSort(buckets[i]);
while(buckets[i].length) {
result.push(buckets[i].shift())
}
}
}
return result;
}
10. 基数排序
从低位排序到高位排序
-
从低位开始,遍历数据的同一位,按照计数排序一样的方式置于数组
-
重复步骤
1,
function radixSort(arr, maxDigit) {
let mod = 10;
let dev = 1;
for (let i = 1; i <= maxDigit; i++, dev *= 10, mod *= 10) {
const digitArr = [];
for (let j = 0, len = arr.length; j < len; j++) {
const num = parseInt((arr[j] % mod) / dev)
digitArr[num] = digitArr[num] || [];
digitArr[num].push(arr[j]);
}
arr = [];
for (let j = 0, len = digitArr.length; j < len; j++) {
const curArr = digitArr[j] || [];
for (let n = 0, lenA = curArr.length; n < lenA; n++) {
arr.push(curArr[n]);
}
}
}
return arr;
}