前言
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情
每天都给自己先打个气,加油加油,送给大家的一句话:人生不可能总是顺心如意,但持续朝着阳光走,影子就会躲在身后。刺眼却是对的方向,逆风更适合飞翔。
五种常见的排序算法
- 排序是什么:把某个乱序的数组变成升序或者降序的方法
- js中的排序:数组的sort方法
冒泡排序,选择排序,插入排序,归并排序,快速排序这几种排序方法你都会了嘛?顺序搜索,二分搜索搜索方式
在介绍这几种排序方法之前,先给大家推荐一个很好用的算法网站
冒泡排序
- 实现冒泡排序的思路
-
- 比较所有相邻元素,如果第一个比第二个大,则交换他们
- 一轮下来,可以保证最后的一个数是最大的
- 执行n-1轮,就可以完成排序
- 下面是实现的方式:
Array.prototype.bubbleSort = function(){
for(let i = 0 ; i<this.length-1; i++){
for(let j =0 ;j<this.length - i -1 ;j++){
if(this[j] > this[j+1]){
let temp = this[j]
this[j] = this[j+1]
this[j+1] = temp
}
}
}
}
let arr = [5,4,3,2,1]
arr.bubbleSort()
- 分析时间复杂度:o(n^2)
选择排序
- 实现选择排序的思路
-
- 找到数组中的最小值,选中它并将其放在第一位
- 接着找到第二小的值,选中它并将其放在第二位
- 以此类推,执行n-1轮
- 实现方式
Array.prototype.selectionSort = function(){
for(let i = 0 ;i<this.length - 1;i++){
let indexMin = i
for(let j = i ;j<this.length;j++){
if(this[j] <this[indexMin]){
indexMin = j
}
}
if(indexMin !== i){
let temp = this[i]
this[i] = this[indexMin]
this[indexMin] = temp
}
}
}
const arr = [5,4,3,2,1]
arr.selectionSort()
- 时间复杂度:o(n^2)
插入排序算法
- 实现思路
-
- 我们从第二个开始,比较当前元素前面的所有元素。
- 找到一个比他大的元素,就把这个元素向后移一位。
- 直到没有比他大的元素了,这个位置就是它的归宿
- 实现方式
Array.prototype.insertionSort = function(){
for(let i = 1 ;i<this.length;i++){
let temp = this[i]
let j = i
while(j > 0){
if(this[j - 1] > temp){
this[j] = this[j - 1]
}else{
break
}
j--
}
this[j] = temp
}
}
let arr = [5,4,3,2,1]
arr.insertionSort()
console.log(arr);
归并排序
- 归并排序思路
-
- 分:把数组劈成两半,在递归对子数组进行“分操作”,直到分成一个个单数的数
- 合:把两个数合并为有序数组,再对有序数组进行合并,直到全部子数组合并为一个完整的数组
- 合并两个有序数组
-
- 新建一个空数组res,用于存在最终排序后的数组
- 比较两个有序数组的头部,较小者出队并推入res中
- 如果两个数组还有值,就重复第二步
- 实现方式
Array.prototype.mergeSort = function(){
const rec = (arr) => {
if(arr.length === 1) return arr
const mid = Math.floor(arr.length/2)
const left = arr.slice(0,mid)
const right = arr.slice(mid,arr.length)
const orderLeft = rec(left)
const orderRight = rec(right)
const res = []
while(orderLeft.length || orderRight.length){
if(orderLeft.length && orderRight.length){
res.push(orderLeft[0] < orderRight[0]?orderLeft.shift():orderRight.shift())
}else if(orderLeft.length){
res.push(orderLeft.shift())
}else if(orderRight.length){
res.push(orderRight.shift)
}
}
return res
}
const res = rec(this)
console.log(res);
res.forEach((n,i) => this[i] = n)
}
let arr = [5,4,3,2,1]
arr.mergeSort()
console.log(arr);
- 时间复杂度分析
-
- 分的时间复杂度为O(logN)
- 合的时间复杂度为O(n)
- 时间复杂度为O(n*logn)
两种搜索算法
顺序搜索
- 实现思路
-
- 遍历数组
- 找到跟目标值相等的元素,就返回他的下标
- 遍历结束后,没有搜索到目标值,就返回-1
- 实现代码
Array.prototype.sequentialSearch = function(item) {
for (let index = 0; index < this.length; index++) {
if(this[index] === item){
return index
}
}
return -1
}
const res = [1,2,3,4].sequentialSearch(3)
- 时间复杂度分析:O(n)
二分搜索
- 实现思路
-
- 从数组的中间元素开始,如果中间元素正好是目标值,则搜索结束
- 如果目标值大于或者小鱼中间元素,则在大于或小于中间元素的那一半数组中搜索
- 实现代码
Array.prototype.binarySearch = function(item){
let low = 0
let high = this.length -1
while(low <= high){
const mid = Math.floor((low + high)/2)
const element = this[mid]
if(element< item){
low = mid + 1
}else if(element > item){
high = mid -1
}else{
return mid
}
}
return -1
}
const res = [1,2,3,4,5].binarySearch(5)
- 时间复杂度分析O(logN)
说个题外话:大家觉得这个二分搜索,像不像我们平时喝酒猜数字的游戏,哈哈哈,想着我们喝的不是酒,喝出来的还是一个算法,有什么问题,请大佬们请教