面试官不知考啥就会随口问:排序算法

本文深入讲解了五种经典的排序算法:冒泡排序、选择排序、插入排序、快速排序及三路快排。每种算法均附带JavaScript实现代码,详细解析了其工作原理与时间复杂度,帮助读者理解算法细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

面试官:能说下(or手写)快速排序原理不?

菜鸡:我忘了不好意思 = =

以上场景是致命的

数年经验的开发者,忘掉具体代码也是分分钟的事。

所以写下来,每当面试前,温习一边就完事了。

 

所用语言:JavaScript

涉及算法:冒泡、

 

(一)冒泡排序(Bubble Sort)

简述:在数组开头,一对一对地取,一个一个地往后推。取出来的一对进行比较,顺序不对则换位。排序总是后面的比前面的先好。

 1 function bubble(elements) {
 2   for(let i = 0; i < elements.length - 1; i++) {
 3     let quit = true
 4     for(let j = 0; j < elements.length - 1 - i; j++) {
 5       if(elements[j] < elements[j+1]) {
 6         //一对交换
 7         let swap = elements[j]
 8         elements[j] = elements[j+1]
 9         elements[j+1] = swap
10         //发生换位,取消退出
11         quit = false
12       }
13     }
14     //里层循环并没有产生换位,说明整个数集已经好了
15     if(quit) break
16   }
17 
18   return elements
19 }

时间复杂度:最好的情况是本来就排好了的,跑第一次最里层循环就可以退出了,O(n)

                      否则,两层循环,复杂度为O(n2)

(二)选择排序(Selection Sort)

简述:在未排序数集中,选出最小的元素,放在数集开头,然后再重复这个动作。

 1 function selection(elements) {
 2   for(let i = 0; i < elements.length - 1; i++) {
 3     // i 上界减1给j预留位置
 4     for(let j = i + 1; j < elements.length; j++) {
 5       if(elements[i] > elements[j]) {
 6         let temp = elements[i]
 7         elements[i] = elements[j]
 8         elements[j] = temp
 9       }
10     }
11   }
12 
13   return elements
14 }

时间复杂度:两层循环,明显的O(n2)

 

(三)插入排序(Insertion Sort)

简述:在未排序数集中取一个,在前面的已排序集中从后向前逐个比较,插入到应在的位置。重复前面步骤。

 1 function insertion(elements) {
 2   for(let i = 1; i < elements.length; i++) {
 3     //第0个已排序好
 4     if(elements[i] < elements[i-1]) {
 5       //暂时最大值直接归并到已排序最后一位,省去插入
 6       let tmp = elements[i]
 7       let j = i - 1
 8       elements[i] = elements[j]
 9 
10       while(j >= 0 && tmp < elements[j]) {
11         elements[j+1] = elements[j]
12         j--
13       }
14 
15       elements[j+1] = tmpi
16     }
17   }
18 
19   return elements
20 }

时间复杂度:O(n2)

额外空间:O(1)

 

(四)快速排序

简述:分而治法。取一个标杆,大于它的站右边,小于它的站左边。得出的两个子集继续取各自的标杆站队。直至子集不可再分。

时间复杂度:最坏的情况是已排好序列,O(n2)

                      最好、平均情况是 O(nlogn) 2为底

 

(五)三路快排

简述:对快排的优化:标志位的选择为随机,分出三个子集来应对等于标志位的情况。

 1 function quickThree(elements) {
 2   __quickThree(elements, 0, elements.length - 1)
 3   return elements
 4 }
 5 
 6 function __quickThree() {
 7   if (start > end) {
 8     return
 9   }
10 
11   let rand = Math.round(Math.random() * (end - start))
12   //随机选出的标志位放在首位
13   [elements[start], elements[start + rand]] = [elements[start + rand], elements[start]]
14   let flag = elements[start]
15 
16   let lt = start
17   let gt = end + 1
18   let i = start + 1
19   while(i < gt) {
20     if (elements[i] < flag) {
21       [elements[i], elements[lt + 1]] = [elements[lt + 1], elements[i]]
22       lt++
23       i++
24     } else if (elements[i] > flag) {
25       [elements[i], elements[gt - 1]] = [elements[gt - 1], elements[i]]
26       gt--
27       //后面换上来的,未经比较,因此 i 不自增,继续滚入while校验
28     } else {
29       i++
30     }
31   }
32   //标志位放回它应在的地方
33   [elements[start], elements[lt]] = [elements[lt], elements[start]]
34   __quickThree(elements, status, lt - 1)
35   __quickThree(elements, gt, end)
36 }

lt——i之间是小于哨兵的、i——gt之间是等于哨兵的,gt——end是大于哨兵的

 

转载于:https://www.cnblogs.com/vincentfong/p/11091515.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值