- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 565718 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174938
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
动画:面试官问我插入排序和冒泡排序哪个更牛逼?
( c6 v6 L+ W. |# z P- K2 b- Y, m& N5 V$ @) e
写在前边8 i" D/ H8 ~% H C0 Z. [
3 o1 V0 g- A( Z! E
" m N" ^" C) I: z% _& ]0 e7 V
排序对于每个开发者来讲,都多多少少知道几个经典的排序算法,比如我们之前以动画形式分享的冒泡排序,也包括今天要分享的插入排序。还有一些其他经典的排序,小鹿整理的共有十种是面试常问到的,冒泡排序、插入排序、希尔排序、选择排序、归并排序、快速排序、堆排序、桶排序、计数排序、基数排序。
- S$ J4 C! x) H4 e8 Z' j- c7 v( }5 V% v0 `) O0 C$ r
虽然我们基本知道了这些排序算法,但是在实际项目开发以及面试中往往出乎我们所料。在面试中,经常会被问到各种排序之间的比较;在实际项目中,往往排序的数据不是我们所练习的整数。/ m5 `% a: `' v! t+ b F
' _- ^: I( g1 J* z那么今天我们来学习一下,插入排序比我们之前讲的冒泡排序有什么区别呢?面试官问我们,我们如何回答完整呢?8 C4 l# p3 s: g9 k0 b
" X1 L& ~/ B6 Y( a; W思维导图* E: A+ |. ]- j& D
$ x/ @) n" w% O( c- X6 a* R# \
# J$ S3 W& N0 S b/ ]# a' O# }4 S+ i; m3 [( U' q
) V( O T. H/ u& m
1- `0 m+ b2 [# B+ h' r+ p" |
/ U" x( G7 {/ {- D/ P如何分析一个排序算法?
9 c( b' @ B) o; V9 n( {
) h: T( w/ T6 Y) q6 h之前写的一篇很详细的文章。: Q" Y+ n3 M1 H' k# Y+ T9 |. b4 ]- U
3 [4 Z/ u7 y1 V. J" O9 `7 H佩奇学编程 | 复杂度分析原来这么简单
. W! w$ T0 c- i. x) V# e+ `9 G' ^! g: Y3 P2 O0 K: Y
分析排序算法已经成为我们衡量一个算法优良的重要标准,从以下三个方面入手。9 Q9 U( R, x# R/ s
$ N0 `# g' Y K' j1.1 时间效率
2 b8 z, o- z: e* @
: V5 g1 i, a0 ?8 A/ g这里所谓的实践效率就是时间复杂度,相信大家对于时间复杂度并不陌生。8 k( ]8 v( m# r% b# x
/ B0 Z, y T& ]3 v0 {/ d
复杂度描述的是算法执行时间(或占用空间)与数据规模的增长关系。2 [' {3 L; }8 V4 {8 M& [; o
/ y) ` Y) v% f% C4 t对于时间复杂度的分析,要把最好时间复杂度、最坏时间复杂度、平均时间复杂度分析出来,分别对应了排序算法的最好排序情况、最坏排序情况以及平均排序效率。
. g/ j6 Q* g+ a1 E: K2 j) D8 w) [: C' h m' Y# I
1.2 空间消耗8 L+ a& f$ ^+ T6 B
, i8 e- u" Z O* S$ d所谓的空间消耗对应的是空间复杂度,在排序算法中需要开辟的额外内存空间是多少。如果空间复杂度为 O(1),此时该排序叫做原地排序。( ^- w9 n1 \4 ?. `1 }' n
1 n6 ]$ H5 F' B- y+ S: H注意:是额外的内存空间,存储排序数据消耗的空间不计。4 O9 x* d2 Q- O! ~+ n
, [ r! v8 J5 s/ w, F
1.3 稳定性
) d, Z! ~: u# P# b
; |! b' L: U$ }8 o# ^. b算法的稳定性虽然我们之前接触的很少,但是稳定性也是衡量一个排序算法的重要标准。什么是稳定排序呢?比如有一组有重复待排序的数据,排序前后,重复的数据顺序不变,此时该排序为稳定排序。否则,叫做不稳定排序。它在实际应用中非常重要的,今天我们就不多说,以后会慢慢分享到。
8 b) ^7 \/ D/ u+ N+ |5 [6 v
- a3 D) E! T% J* ~' [8 B" T2
0 `6 k+ w; e+ b' f
, B* L0 t0 ], N2 ?* u; |4 G0 v \什么是插入排序?
, b+ ]; \6 o* ~7 G0 t# q
: c& Z7 L/ E7 U7 g. r顾名思义,插入排序就是通过插入的方式来排序呗,最经典的就是打斗地主,可以将打乱的扑克牌作为未排序区间,手中已经排好序的作为排序区间。每次我们摸牌的过程,就是从未排序区间,通过插入的方式,插入到已排序区间。那么这个过程就称为插入排序。
; P4 l) J! w5 E% \; Z& J9 |' F3 l/ L" j6 ~3 K
' L n% N) d- L0 w. n' W7 y
% t n4 }4 r4 E" W8 Q
3$ B6 e( y6 \" E) g x
6 N4 o7 Z6 d% @: g1 e# B: ]
如何实现插入排序?
6 k3 _2 ]- v/ i+ v4 a; K/ W7 X# M* W* q0 r' }4 o
上述插入排序的概念我们已经理解了,那么给你一组数据,如何来进行插入排序呢?6 X, o. A/ a W6 c7 z/ n
' _' x5 S) Y8 M- S
* w! {$ w/ U9 ?9 {0 k) F$ O, ]. @4 r. N/ i2 j/ ]) N, n
首先我们要将数据划分为两个区间,已排序区间和未排序区间。# ?! J& }* u; J3 w( L
9 Y# X" j: O7 L% }: r
2 m$ g# u( v- Y! ^3 q5 t
2 n" M9 Y6 j' T/ I' J# S& ?% B0 z' A$ e* S) {2 b
' n ~% J9 j. `1 Z8 p! N6 n
我们从未排序区间取出数据和已排序区间的数据进行比较,如果小于已排序区间的数据,那我们就交换数据。
, q' z% J9 }/ y4 W/ x9 E8 m9 ~5 G- V. R
0 L: R1 H4 N8 g' E
: e% T" L6 _: l& ]# T( l
9 m" s; _; S. f( k
0 Q8 D: M0 }7 y0 N6 B- y( m7 d如果交换到已排序区间数据不在大于插入的数据,然后将元素插入进去。% w3 P3 F( n7 d, i5 K2 s5 D2 a
$ D5 Y9 l c- v
- i3 S: s7 h" z7 N: N
( [, G& M/ ^" D4 V# A: ]& D% E0 Y/ K- X: i* J
* F$ H4 F7 E/ o( W5 e3 j
最后我们看一下总的插入排序动画和代码实现。" j# s# X9 w- Q" `
! }* O" m2 U9 Z2 Z
. p' n& G9 a. V) r; ]( r/ [; M" E, [* e
4
) A/ S+ u5 Z# h* ]; w
4 ?: x1 N* s& v/ v) x' k6 L* G O插入排序的性能7 u7 R5 O& y6 c# i+ w
' e9 X" o$ {$ ~3 `% b我们通过上边的对插入排序的拆分讲解和动画以及代码实现,想必面试官让你手写一个插入排序可以轻轻松松写出。但是我们掌握的插入排序知识还往往不够,我们在实际项目中,还要考虑插入排序的性能怎么样?因为才能更好的选择适当排序应用到项目中去。8 K& m8 X: ^: K( I/ d: Q
0 S+ X0 M# w) L1 g$ p q4.1 插入排序的稳定性
3 X. f8 P% U R( q3 b5 M
2 ]9 [; p, _ G9 G2 U* Q1 U% ^再插入排序中,如果存在重复数据的话,前边的元素再插入的过程永远在第二个重复数据的前边,所以插入排序后的重复数据前后顺序不变,所以插入排序是稳定排序算法。
7 l3 f2 U6 P8 t' p# z
7 P+ N% L6 T1 `. w ^" P9 I- `$ P4.2 插入排序的空间消耗
# i9 n; w) g0 L5 d- p
; X& m3 s3 S. N" k% }我们可以发现,插入排序的移动方式,需要消耗常量级的额外内存空间存储,也就是代码中的 temp,所以时间复杂度为 O(1),我们上边讲到,空间复杂度为O(1)的是原地排序算法。4 B' Q2 O( v. k) H7 J' w7 J
5 N7 J6 X+ \. E7 a ]( @
4.3 插入排序的时间效率
) E: U; j( B1 q/ a V, @0 L
! y2 ]" t1 m: F9 a2 ^插入排序的最好情况就是不需要搬移任何数据,从头到尾寻找插入数据,每次只比较一次即可,即一组有序数据,所以最好时间复杂度为O(n)。 F' A4 I- g* v* u1 w
: O' U- Y- N/ r$ ~3 H' F2 f如果一组数据正好是倒序输出,那么每次都需要比较移动所有数据,每次移动时 n,n 个数据时间复杂度为O(n2)。+ e" X" h, l. W* x5 i1 {+ O5 ]
& s7 W2 ^; i& O' M( O( r
对于插入排序的平均时间复杂度,每次插入都要移动数据,插入 n 次,所以平均时间复杂度为 O(n2)。
1 {2 v) }) }. ^' O: p0 R- L( h. W* M7 |1 \$ W. \2 y
55 v W/ E5 H# b7 _
2 S' Z4 f% V& v8 I0 A小结+ H' U1 D# Q4 F7 }) ?- j1 ^$ G
3 B9 J! S7 ~6 T: _8 V
我们学完了今天的插入排序之后,我们回到最初的面试官问题上。插入排序和冒泡排序哪个更好呢?& g7 j0 z( Q4 R2 [) z
' w; A6 C$ Q, K7 D, W7 }6 Y% X我们现在元素移动次数上进行分析,如果一组无序的数据通过冒泡排序排好序之后,它的交换次数是这种数据的逆序度;对于插入排序来说也是一样的,移动次数上都是原本数据的逆序度。 N8 _7 y. @) C/ z8 l
4 g$ w7 D9 I* P% e9 P
元素的移动次数是相同的,那我们接下来看看元素的交换次数。从代码上分析可以明显看出,冒泡排序的一次交换需要三行代码,而插入排序的交换却需要一行,所以总的交换次数冒泡排序大于插入排序。' z8 T$ Q4 m/ d1 V2 x
% \ Y; `% i( @2 a: n
有小伙伴会问,这两行的差别有那么大吗?移动一次,我们可以不计较,如果数据很多,想想下,两者的效率差别很轻易的就比较出来了。0 V7 B* F# V) E* U9 E
( A4 A9 B. f0 ^# N/ F虽然冒泡排序的时间复杂度和插入排序的时间复杂度是相同的,但是我们实际使用中还是优先选择插入排序。2 g3 ~2 u& e7 ?2 {3 I) B7 g
: L* E/ v# v: u
对于插入排序还是可以优化的,对了,没错,就是希尔排序,我们在这不多分开写,后期会继续更新。" h I! z2 x- x2 y& B" F
————————————————
" w7 M1 s1 l, n) v版权声明:本文为CSDN博主「胡鹏程的博客」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。. K2 j4 T, [9 j6 y7 {% W
原文链接:https://blog.csdn.net/lyshark_lyshark/article/details/1267927081 J2 d1 C# A7 u) g/ q; Q
; X u3 U4 n( O& ^# v* r7 H& f( p' s& e
|
zan
|