6种排序如下👇
- 冒泡排序
- 计数排序
- 快速排序
- 归并排序
- 插入排序
- 选择排序
时间复杂度如下图👇
冒泡排序
这个名字的由来是向泡泡一样浮起来,脑补一下,就是每次比较相邻的两个元素大小,然后慢慢'漂浮'起来,我瞎掰的,看思路吧。
「时间复杂度O(n^2)」
思路
- 比较相邻的元素,前者比后者大的话,两者交换位置。
- 对每一对相邻元素做相同操作,从开始第一对到最后一对,这样子最后的元素就是最大元素。
- 针对n个元素重复以上步骤,每次循环排除当前最后一个。
- 重复步骤1~3,直到排序完成。
动画
冒泡排序
代码实现
let quickSort = function (arr) {
// 递归出口就是数组长度为1
if (arr.length <= 1) return arr
//获取中间值的索引,使用Math.floor向下取整;
let index = Math.floor(arr.length / 2)
// 使用splice截取中间值,第一个参数为截取的索引,第二个参数为截取的长度;
// 如果此处使用pivot=arr[index]; 那么将会出现无限递归的错误;
// splice影响原数组,splice影响原数组,应当被删除
let pivot = arr.splice(index, 1)[0],
left = [],
right = [];
for (let i = 0; i < arr.length; i++) {
if (pivot > arr[i]) {
left.push(arr[i])
} else {
right.push(arr[i])
}
}
return quickSort(left).concat([pivot], quickSort(right));
}
<span class="hljs-comment">//let arr = [2, 9, 6, 7, 4, 3, 1, 7]</span>
<span class="hljs-comment">// console.log(quickSort(arr))</span></pre><hr><h2 id="item-4">归并排序<span class="emoji emoji-star"></span></h2><p>将两个有序数列合并成一个有序数列,我们称之为“归并”</p><p>基本思想与过程:先递归的分解数列,再合并数列(分治思想的典型应用)</p><p><strong>「时间复杂度: O(nlog(n))」</strong></p><h3 id="item-4-10">思路</h3><ol><li>将一个数组拆成A、B两个小组,两个小组继续拆,直到每个小组只有一个元素为止。</li><li>按照拆分过程逐步合并小组,由于各小组初始只有一个元素,可以看做小组内部是有序的,合并小组可以被看做是合并两个有序数组的过程。</li><li>对左右两个小数列重复第二步,直至各区间只有1个数。</li></ol><h3 id="item-4-11">动画</h3><p>归并排序</p><h3 id="item-4-12">代码实现</h3><div class="widget-codetool" style="display: none;">
<div class="widget-codetool--inner">
<button type="button" class="btn btn-dark rounded-0 sflex-center copyCode" data-toggle="tooltip" data-placement="top" data-clipboard-text="const merge = (left, right) => { // 合并数组
let result = []
// 使用shift()方法偷个懒,删除第一个元素,并且返回该值
while (left.length && right.length) {
if (left[0] <= right[0]) {
result.push(left.shift())
} else {
result.push(right.shift())
}
}
while (left.length) {
result.push(left.shift())
}
while (right.length) {
result.push(right.shift())
}
return result
}
let mergeSort = function (arr) {
if (arr.length <= 1)
return arr
let mid = Math.floor(arr.length / 2)
// 拆分数组
let left = arr.slice(0, mid),
right = arr.slice(mid);
let mergeLeftArray = mergeSort(left),
mergeRightArray = mergeSort(right)
return merge(mergeLeftArray, mergeRightArray)
}
let arr = [2, 9, 6, 7, 4, 3, 1, 7, 0, -1, -2]
console.log(mergeSort(arr))" aria-label="复制" data-bs-original-title="复制">
<i class="far fa-copy"></i>
</button>
</div>
const merge = (left, right) => { // 合并数组
<span class="hljs-keyword">let</span> result = []
<span class="hljs-comment">// 使用shift()方法偷个懒,删除第一个元素,并且返回该值</span>
<span class="hljs-keyword">while</span> (left.<span class="hljs-property">length</span> && right.<span class="hljs-property">length</span>) {
<span class="hljs-keyword">if</span> (left[<span class="hljs-number">0</span>] <= right[<span class="hljs-number">0</span>]) {
result.<span class="hljs-title function_">push</span>(left.<span class="hljs-title function_">shift</span>())
} <span class="hljs-keyword">else</span> {
result.<span class="hljs-title function_">push</span>(right.<span class="hljs-title function_">shift</span>())
}
}
<span class="hljs-keyword">while</span> (left.<span class="hljs-property">length</span>) {
result.<span class="hljs-title function_">push</span>(left.<span class="hljs-title function_">shift</span>())
}
<span class="hljs-keyword">while</span> (right.<span class="hljs-property">length</span>) {
result.<span class="hljs-title function_">push</span>(right.<span class="hljs-title function_">shift</span>())
}
<span class="hljs-keyword">return</span> result
}
<span class="hljs-keyword">let</span> mergeSort = <span class="hljs-keyword">function</span> (<span class="hljs-params">arr</span>) {
<span class="hljs-keyword">if</span> (arr.<span class="hljs-property">length</span> <= <span class="hljs-number">1</span>)
<span class="hljs-keyword">return</span> arr
<span class="hljs-keyword">let</span> mid = <span class="hljs-title class_">Math</span>.<span class="hljs-title function_">floor</span>(arr.<span class="hljs-property">length</span> / <span class="hljs-number">2</span>)
<span class="hljs-comment">// 拆分数组</span>
<span class="hljs-keyword">let</span> left = arr.<span class="hljs-title function_">slice</span>(<span class="hljs-number">0</span>, mid),
right = arr.<span class="hljs-title function_">slice</span>(mid);
<span class="hljs-keyword">let</span> mergeLeftArray = <span class="hljs-title function_">mergeSort</span>(left),
mergeRightArray = <span class="hljs-title function_">mergeSort</span>(right)
<span class="hljs-keyword">return</span> <span class="hljs-title function_">merge</span>(mergeLeftArray, mergeRightArray)
}
<span class="hljs-keyword">let</span> arr = [<span class="hljs-number">2</span>, <span class="hljs-number">9</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">4</span>, <span class="hljs-number">3</span>, <span class="hljs-number">1</span>, <span class="hljs-number">7</span>, <span class="hljs-number">0</span>, -<span class="hljs-number">1</span>, -<span class="hljs-number">2</span>]
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-title function_">mergeSort</span>(arr))</pre><hr><h2 id="item-5">插入排序<span class="emoji emoji-star"></span></h2><p>顾名思义:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。</p><p><strong>「时间复杂度: O(n^2)」</strong></p><h3 id="item-5-13">思路</h3><ol><li>从第一个元素开始,该元素可以认为已经被排序;</li><li>取出下一个元素,在已经排序的元素序列中从后向前扫描;</li><li>如果该元素(已排序)大于新元素,将该元素移到下一位置;</li><li>重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;</li><li>重复步骤2~5。</li></ol><h3 id="item-5-14">动画</h3><p></p><h3 id="item-5-15">代码实现</h3><div class="widget-codetool" style="display: none;">
<div class="widget-codetool--inner">
<button type="button" class="btn btn-dark rounded-0 sflex-center copyCode" data-toggle="tooltip" data-placement="top" data-clipboard-text="let insertionSort = function (arr) {
let len = arr.length
// 双指针,当前和前一个
for (let i = 0; i < len; i++) {
let preIndex = i - 1,
cur = arr[i];
// 第一个元素无前一个元素,可以直接赋值
while (preIndex >= 0 && arr[preIndex] > cur) {
arr[preIndex + 1] = arr[preIndex]
preIndex--;
}
arr[preIndex + 1] = cur
}
return arr
}
let arr = [2, 9, 6, 7, 4, 3, 1, 7, 0, -1, -2]
console.log(insertionSort(arr))" aria-label="复制" data-bs-original-title="复制">
<i class="far fa-copy"></i>
</button>
</div>
let insertionSort = function (arr) {
let len = arr.length
// 双指针,当前和前一个
for (let i = 0; i < len; i++) {
let preIndex = i - 1,
cur = arr[i];
// 第一个元素无前一个元素,可以直接赋值
while (preIndex >= 0 && arr[preIndex] > cur) {
arr[preIndex + 1] = arr[preIndex]
preIndex--;
}
arr[preIndex + 1] = cur
}
return arr
}
<span class="hljs-keyword">let</span> arr = [<span class="hljs-number">2</span>, <span class="hljs-number">9</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">4</span>, <span class="hljs-number">3</span>, <span class="hljs-number">1</span>, <span class="hljs-number">7</span>, <span class="hljs-number">0</span>, -<span class="hljs-number">1</span>, -<span class="hljs-number">2</span>]
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-title function_">insertionSort</span>(arr))</pre><hr><h2 id="item-6">选择排序<span class="emoji emoji-star"></span></h2><p>思路:每一次从待排序的数组元素中选择<strong>最大(最小)的一个元素作为首元素</strong>,直到排完为止</p><p><strong>「时间复杂度O(n^2)」</strong></p><h3 id="item-6-16">思路</h3><ol><li>有n个数,需要排序n-1次</li><li>第一次选择最小值,放在第一位</li><li>第二次选择最小值,放在第二位</li><li>…..重复该过程</li><li>第n-1次选择最小值,放在第n-1位</li></ol><h3 id="item-6-17">动画</h3><p></p><h3 id="item-6-18">代码实现</h3><div class="widget-codetool" style="display: none;">
<div class="widget-codetool--inner">
<button type="button" class="btn btn-dark rounded-0 sflex-center copyCode" data-toggle="tooltip" data-placement="top" data-clipboard-text="let selectSort = function (arr) {
let len = arr.length,
temp = 0;
// 一共需要排序len-1次
for (let i = 0; i < len - 1; i++) {
// 设定替换目标,从数组的第一个开始
temp = i;
for (let j = i + 1; j < len; j++) {
if (arr[j] < arr[temp])
temp = j;
}
// 每一趟保证第i位为最小值
if (temp !== i) {
[arr[i], arr[temp]] = [arr[temp], arr[i]]
}
}
return arr
}
let arr = [2, 9, 6, 7, 4, 3, 1, 7, 0, -1, -2]
console.log(selectSort(arr))" aria-label="复制" data-bs-original-title="复制">
<i class="far fa-copy"></i>
</button>
</div>
let selectSort = function (arr) {
let len = arr.length,
temp = 0;
// 一共需要排序len-1次
for (let i = 0; i < len - 1; i++) {
// 设定替换目标,从数组的第一个开始
temp = i;
for (let j = i + 1; j < len; j++) {
if (arr[j] < arr[temp])
temp = j;
}
// 每一趟保证第i位为最小值
if (temp !== i) {
[arr[i], arr[temp]] = [arr[temp], arr[i]]
}
}
<span class="hljs-keyword">return</span> arr
}
<span class="hljs-keyword">let</span> arr = [<span class="hljs-number">2</span>, <span class="hljs-number">9</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">4</span>, <span class="hljs-number">3</span>, <span class="hljs-number">1</span>, <span class="hljs-number">7</span>, <span class="hljs-number">0</span>, -<span class="hljs-number">1</span>, -<span class="hljs-number">2</span>]
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-title function_">selectSort</span>(arr))</pre><p></p><p></p>