一、冒泡排序
原理:
1、相邻元素两两比较,如果前一个比后一个大,则交换位置
2、第一轮比较完毕,最后一个元素是最大的元素
3、第二轮比较开始,此时最后一个元素是最大的,所以不参与比较
代码:
function bubble(arr = [3, 1, 7, 4, 8, 2, 6]){
let len = arr.length
for(let i = 0; i < len - 1; i++){
for(let j = 0; j < len - 1 - i; j++){
if(arr[j] > arr[j + 1]){
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
}
}
}
return arr
}
二、选择排序
原理:
1、首先在未排序序列中找到最小元素,存放到排序序列的起始位置
2、第一轮比较完毕,第一个元素是最小的元素
3、第二轮比较开始,此时第一个元素是最小的,所以不参与比较
代码:
function choose(arr = [5, 2, 7, 1, 4, 9, 6]) {
let minIndex
for (var i = 0; i < arr.length - 1; i++) {
minIndex = i;
for (var j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j // 将最小数的索引保存
}
}
[arr[minIndex], arr[i]] = [arr[i], arr[minIndex]]
}
return arr
}
三、插入排序(玩扑克牌的算法)
原理:
1、每次拿到一张牌,按大小顺序将其插入到合适的位置
代码:
function insert(arr = [2, 5, 3, 7, 1, 11, 4]){
for(let i = 1; i < arr.length; i++){
let temp = arr[i]
let j = i
arr[j] = arr[j - 1]
j--
arr[j] = temp
}
return arr
}
四、希尔排序(缩小增量排序)
原理:
1、将整个待排序记录序列分割为若干个子序列
2、然后对每一个子序列进行直接插入排序
代码:
function shellSort(arr = [3, 5, 1, 8, 2, 6]) {
let gap = Math.floor(arr.length / 2)
while(1 <= gap){
for(let i = gap; i < arr.length; i++){
let temp = arr[i]
let j = 0
for(j = i - gap; j >=0 && temp < arr[j]; j-=gap){
arr[j + gap] = arr[j]
}
arr[j + gap] = temp
}
gap = Math.floor(gap / 2)
}
return arr
}
五、归并排序
原理:
1、把长度为n的输入序列分成两个长度为n/2的子序列
2、对这两个子序列分别采用归并排序
3、将两个排序好的子序列合并成一个最终的排序序列
代码:
function mergeSort(arr = [3, 7, 4, 1, 6, 5]){
let len = arr.length
if(len <= 1){
return arr
}
let
num = Math.floor(len / 2),
left = mergeSort(arr.slice(0, num))
right = mergeSort(arr.slice(num, len))
return merge(left, right)
function merge(left, right){
let l = 0, r = 0, result = []
while(l < left.length && r < right.length){
if(left[l] < right[r]){
result.push(left[l])
l++
}else{
result.push(right[r])
r++
}
}
result = result.concat(left.slice(l, left.length))
result = result.concat(right.slice(r, right.length))
return result
}
}
六、快速排序
原理:
1、找基准(一般是以中间项为基准)
2、遍历数组,小于基准的放在左边,大于基准的放在右边
3、递归
代码:
function quickSort(arr = [3, 7, 20, 1, 10, 6, 15, 5, 12]) {
if (arr.length <= 1) return arr
const leftArr, rightArr = [],
let current = null
current = arr.splice(0, 1)
for (let i = 0; i < arr.length; i++) {
arr[i] < current ? leftArr.push(arr[i]) : rightArr.push(arr[i])
}
return quickSort(leftArr).concat(current, quickSort(rightArr))
}
七、堆排序(完全二叉树)
原理:
1、将无序序列构建成一个堆,一般升序采用大顶堆,降序采用小顶堆
2、将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端
3、重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。
代码:
// 构造大顶堆
function shiftDown(arr, i, arrLenth){
let temp = arr[i]
for(let j = 2 * i + 1; j < arrLenth; j = 2 * i + 1){
temp = arr[i]
if(j + 1 < arrLenth && arr[j] < arr[j + 1]){
j++ //到两个孩子中较大的一个,再与父节点比较
}
if(temp < arr[j]){
[arr[i], arr[j]] = [arr[j], arr[i]]
i = j
}else{
break
}
}
}
// 堆排序
function heapSort(arr = [4, 6, 8, 5, 9]){
// 从第一个非页子节点开始
for(let i = Math.floor(arr.length / 2 - 1); i >= 0; i--){
shiftDown(arr, i, arr.length)
}
// 排序,每一次for循环找出一个当前最大值,数组长度减一
for(let i = Math.floor(arr.length - 1); i > 0; i--){
[arr[i], arr[0]] = [arr[0], arr[i]] //根节点与最后一个节点交换
shiftDown(arr, 0, i)
}
return arr
}
八、计数排序
原理:
1、查找待排序数组中最大的元素
2、统计每个值为i的元素的出现次数并累计
3、反向填充目标数组,将每个元素i放在新数组的第C[i]项,每放一个元素,计数-1
代码:
function countSort(nums = [2, 3, 8, 7, 1, 2, 7, 3]) {
let arr = [];
let max = Math.max(...nums);
let min = Math.min(...nums);
// 装桶
for (let i = 0, len = nums.length; i < len; i++) {
let temp = nums[i];
arr[temp] = arr[temp] + 1 || 1;
}
let index = 0;
// 还原原数组
for (let i = min; i <= max; i++) {
while (arr[i] > 0) {
nums[index++] = i;
arr[i]--;
}
}
return nums
}
九、桶排序
原理:
1、设置一个定量的数组当作空桶
2、遍历输入数据,并且把数据一个一个放到对应的桶里去
3、对每个不是空的桶进行排序
4、从不是空的桶里把排好序的数据拼接起来。
代码:
function bucket_sort(A = [29, 25, 3, 49, 9, 37, 21, 43], k = 5, s = 10) { //A排序数组,k桶子数量,s桶子空间尺度
const buckets = Array.from({ length: k }, () => []) //创建桶子
//把元素放入对应桶子
for (let i = 0; i < A.length; i++) {
//计算需要放入桶子序号
const idx = ~~(A[i] / s)
buckets[idx].push(A[i])
}
//对每个桶子进行排序
for (let i = 0; i < buckets.length; i++) {
//此处选取插入排序, 空间消耗少,元素少常数时间消耗短
insert(buckets[i])
}
//把每个桶子数据合并
return [].concat(...buckets)
}
十、基数排序
原理:
1、确定数组中的最高位数
2、按数组中每个元素的个位大小进行排序,接着是十位、百位...
3、类似桶排序
代码:
function radixSort(arr = [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48], maxDigit = 2) {
let mod = 10, dev = 1, counter = []
for(let i = 0; i < maxDigit; i++, dev *= 10, mod *= 10){
for(let j = 0; j < arr.length; j++){
let bucket = parseInt((arr[j] % mod) / dev)
if(counter[bucket] == null){
counter[bucket] = []
}
counter[bucket].push(arr[j])
}
let pos = 0
for(let j = 0; j < counter.length; j++){
let value = null
if(counter[j] != null){
while((value = counter[j].shift()) != null){
arr[pos++] = value
}
}
}
}
return arr
}