Js实现冒泡排序
// 是一种计算机科学领域的较简单的排序算法
// 它重复的走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小,首字母)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是该元素列已经排序完成。
冒泡排序是效率最低的排序算法,由于算法嵌套了两轮循环,所以时间复杂度委O(n^2)
最好的情况给出一个已经排序的数组进行冒泡排序,时间复杂度为O(n)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| // 冒泡排序 function bubbleSort(arr) { let len = arr.length; // 遍历数组的长度,以确定循环次数 for (let i = 0; i < len;i++) { // 遍历数组len次,忽略后面的i项 for (let j = 0; j < len - 1 - i; j++) { // 将每一项与后一项进行对比,不符合要求的就换位 if (arr[j] > arr[j + 1]) { [arr[j + 1], arr[j]] = [arr[j], arr[j + 1]] } } } return arr }
|
实现一个快排
快速排序:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行上述递归排序,以此达到整个数据变成有序序列,时间复杂度为 O(n log n)。
// 1.Quickersort通过数组选取一个元素表示为基准点,把数组中的所有其他元素分为两类-(大于和小于此基准点的数组)
// 2.然后把作为这一轮排序结果的两个数组(数组元素都小于基准点的数组和数组元素都大于基准点的数组)再进行相同的排序。即分别再选个基准点,然后基于基准点分为两个数组元素分别小于和大于基准点的数组。
// 3.最终,由于最后数组中没有元素或只有一个元素,因此不用再比较了。剩下的值都已经基于基准点拍好序了。
(时间复杂度(平均)O(nlogn))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const quickSort1 = arr => { if (arr.length <= 1) { return arr; } const midIndex = Math.floor(arr.length / 2) const arrArr = arr.splice(midIndex, 1) const midIndexVal = arrArr[0] const left = [] const right = [] for (let i = 0; i < arr.length; i++) { if (arr[i] < midIndexVal) { left.push(arr[i]); } else { right.push(arr[i]) } } return quickSort1(left).concat(midIndexVal, quickSort1(right)); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| // 快速排序 const testQuickSort = arr => { if (arr.length <= 1) { return arr; } const mid = arr[0];// 基准值 const left = [] const right = []; for (let i = 1; i < arr.length; i++) { if (arr[i] < mid) { left.push(arr[i]) } else { right.push(arr[i]) } } return [...testQuickSort(left), mid, ...testQuickSort(right)] }
|
选择排序 (O^2)
从上面可以看到,对于具有 n 个记录的无序表遍历 n-1 次,第i 次从无序表中第 i 个记录开始,找出后序关键字中最小的记录,然后放置在第 i 的位置上
直至到从第n个和第n-1个元素中选出最小的放在第n-1个位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
function testSelectSort(arr) { let len = arr.length; let minIndex; for (let i = 0; i < len - 1; i++) { minIndex = i; for (let j = 0; j < len; j++) { if (arr[j] < arr[minIndex]) { minIndex = j; } } [arr[i], arr[minIndex]] = arr[minIndex], arr[i]; } return arr; }
|
第一次内循环比较N - 1次,然后是N-2次,N-3次,……,最后一次内循环比较1次 共比较的次数是 (N - 1) + (N - 2) + … + 1,求等差数列和,得 (N - 1 + 1)* N / 2 = N^2 / 2,舍去最高项系数,其时间复杂度为 O(N^2)
从上述也可以看到,选择排序是一种稳定的排序
插入排序
// 插入排序
// 将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
// 从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置
// 如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function testInsertSort(arr) { const len = arr.length; let preIndex, current; for (let 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 3 4 5 6 7 8 9 10
| function InsertSort(arr) { for (let i = 0; i < arr.length; i++) { for (let j = 0; j < i; j++) { if (arr > arr) { = } } } return arr; }
|
// 在插入排序中,当待排序数组是有序时,是最优的情况,只需当前数跟前一个数比较一下就可以了,这时一共需要比较N- 1次,时间复杂度为O(n)
// 最坏的情况是待排序数组是逆序的,此时需要比较次数最多,总次数记为:1+2+3+…+N-1,所以,插入排序最坏情况下的时间复杂度为O(n^2)
// 通过上面了解,可以看到插入排序是一种稳定的排序方式
参考文章