- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 563327 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174221
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
动画:面试官问我插入排序和冒泡排序哪个更牛逼?
- }; n; O/ x' K
, W. J- j' Z0 x/ ^: O: H% E写在前边
" z) k9 O1 a6 w3 c
) U* k6 I2 T) T7 W4 ?& {& V. k4 U+ S- m. M, E- w$ |8 V$ [( t, R7 j
排序对于每个开发者来讲,都多多少少知道几个经典的排序算法,比如我们之前以动画形式分享的冒泡排序,也包括今天要分享的插入排序。还有一些其他经典的排序,小鹿整理的共有十种是面试常问到的,冒泡排序、插入排序、希尔排序、选择排序、归并排序、快速排序、堆排序、桶排序、计数排序、基数排序。
- R/ `0 B8 a. g& k" w; o0 y( N9 t5 `! e7 n8 {2 r/ `/ f
虽然我们基本知道了这些排序算法,但是在实际项目开发以及面试中往往出乎我们所料。在面试中,经常会被问到各种排序之间的比较;在实际项目中,往往排序的数据不是我们所练习的整数。! n$ H0 d% p/ ^
0 `0 j8 |9 m6 ?/ M那么今天我们来学习一下,插入排序比我们之前讲的冒泡排序有什么区别呢?面试官问我们,我们如何回答完整呢?
; |" E" Y' U* N3 M4 |
- B: V W3 |5 a& I7 l: j( P0 q* j思维导图
# s7 l6 {& Y, X3 j! [% P) n9 P- d- F' v
! C6 y% |2 n: t3 R" n7 K
' _& @0 I; d6 [
0 N4 a/ r# \3 A5 g- ^) t1. X# A" U* d) L& W! Y9 \
- T+ R, Y9 C0 R: P; j3 B2 I1 \
如何分析一个排序算法?% ?4 g$ s" r, X* l& g" `7 n
& v" Y- p/ S" r
之前写的一篇很详细的文章。
; g/ J$ N- o j( ]+ ?) L$ I5 ~/ s8 T7 g- Z/ X
佩奇学编程 | 复杂度分析原来这么简单
- c |3 R% v/ @2 s1 d
- _5 ~6 v* f$ L% F- h分析排序算法已经成为我们衡量一个算法优良的重要标准,从以下三个方面入手。
4 _! h* _0 n* h! v& j" c3 W& Q" \* b7 R8 C6 `& X3 }4 g3 R6 g
1.1 时间效率/ w! x% }1 E* f C
! b- G* A" F; H& W' G* y" \# b
这里所谓的实践效率就是时间复杂度,相信大家对于时间复杂度并不陌生。
& F! v( I6 l5 e9 U C5 {/ c& H% u2 s) w! n
复杂度描述的是算法执行时间(或占用空间)与数据规模的增长关系。
3 O4 N3 O$ n7 a; q/ L2 B4 `" O) Z
+ ]/ I8 O4 V4 M1 K) s, I对于时间复杂度的分析,要把最好时间复杂度、最坏时间复杂度、平均时间复杂度分析出来,分别对应了排序算法的最好排序情况、最坏排序情况以及平均排序效率。9 A* M3 f9 y+ ]; {( N' v
! S T1 h* ~' t# d u3 Y% u$ c
1.2 空间消耗( P0 q2 B5 F+ _1 I
* G* m2 w! a* Q
所谓的空间消耗对应的是空间复杂度,在排序算法中需要开辟的额外内存空间是多少。如果空间复杂度为 O(1),此时该排序叫做原地排序。8 k9 [! i& J+ {6 I
# k/ r% z( U% e5 e. Y* L% I注意:是额外的内存空间,存储排序数据消耗的空间不计。
4 q, T% B9 J" E# C7 H4 I
. D! r- s& t8 [% `/ H/ Z1.3 稳定性# P" f d4 u" j3 }/ ^; N( @
N W2 v; l, _0 B# V7 S5 n
算法的稳定性虽然我们之前接触的很少,但是稳定性也是衡量一个排序算法的重要标准。什么是稳定排序呢?比如有一组有重复待排序的数据,排序前后,重复的数据顺序不变,此时该排序为稳定排序。否则,叫做不稳定排序。它在实际应用中非常重要的,今天我们就不多说,以后会慢慢分享到。8 O0 e* D* A. V) `- D4 L+ R
, ^1 K5 W5 u1 i) p' y& _2 E' j0 M
2& X) J; f: O* ^. r! O3 M
" d8 L" _" ]% ?) N
什么是插入排序?
" L2 Y; p2 X7 a/ Q. k8 R- ^+ R7 y$ l4 S8 {& R- _
顾名思义,插入排序就是通过插入的方式来排序呗,最经典的就是打斗地主,可以将打乱的扑克牌作为未排序区间,手中已经排好序的作为排序区间。每次我们摸牌的过程,就是从未排序区间,通过插入的方式,插入到已排序区间。那么这个过程就称为插入排序。3 L! I, d7 j! k$ A' Z' P9 K9 ?2 ]
. @' p% I7 g2 b* j( a" k `
6 p, m' n$ D+ z. V. @6 U, k0 L8 a7 d/ Q7 I9 A7 g
3. o; d2 y Q/ e5 _0 T5 N4 ~ I& u2 f
- V! C: S; b! w& i
如何实现插入排序?; w- J% q- C1 m8 y# r
9 Y: V6 @5 Q8 X4 e, i: g: ~上述插入排序的概念我们已经理解了,那么给你一组数据,如何来进行插入排序呢?) ^4 j& y. P) T
1 o* I& {$ _& O5 @6 l. d: }) \! K5 C0 S& r' _. }
p- [% p! t6 D% A8 M3 I" Y首先我们要将数据划分为两个区间,已排序区间和未排序区间。9 @0 ?, a m& I. M
( J+ s( S+ b3 p* G) |& Q/ t4 V
f( ~- b. m, ?% g. X4 X9 i# n
2 u' B& H5 v$ ^7 c" u; x) I7 K4 M5 E
7 V7 \% z O+ C+ k3 v+ X+ Q) `我们从未排序区间取出数据和已排序区间的数据进行比较,如果小于已排序区间的数据,那我们就交换数据。% O9 r' Q! z0 l) q4 C! o% z
n6 `% l e( N& F# d- \) U7 X" U/ u4 S3 o* E6 A. K2 f/ `
0 b3 I7 n& @) z, D9 U& A
+ \: |0 P# p, S' h }
* h9 [+ c0 S7 ?0 i: ?$ g如果交换到已排序区间数据不在大于插入的数据,然后将元素插入进去。
- c5 y; o. j( h3 E/ `1 O1 O; f1 o
9 Y/ ]3 B4 ^' F$ n4 A8 `* @2 k7 b
0 g7 o$ B8 v$ c0 r) X
9 L; E1 W" j" t: N2 g7 ]/ B8 _; C1 q: m4 { k- V/ _) b3 A6 P# x
最后我们看一下总的插入排序动画和代码实现。
; a* L' u. R0 `3 Z4 _8 ]* {, l) q, Q: h" m
' p4 Q' z" Q9 ~7 y0 p: ~
9 N* x$ G$ E3 h40 c7 H5 z* {$ |8 ]/ i. t- Z. I
0 z& ~; J+ n$ @2 ^插入排序的性能) T, C$ S$ v4 V
1 p/ O+ ^4 d, q1 M
我们通过上边的对插入排序的拆分讲解和动画以及代码实现,想必面试官让你手写一个插入排序可以轻轻松松写出。但是我们掌握的插入排序知识还往往不够,我们在实际项目中,还要考虑插入排序的性能怎么样?因为才能更好的选择适当排序应用到项目中去。
0 x7 i' J1 F" c& }$ s1 r5 p T
% C; C) t; U/ |- [8 F4.1 插入排序的稳定性* s$ E& m' b0 X
( Z+ x l0 r x' B' B- @. A1 ]再插入排序中,如果存在重复数据的话,前边的元素再插入的过程永远在第二个重复数据的前边,所以插入排序后的重复数据前后顺序不变,所以插入排序是稳定排序算法。1 l. ~7 y- B% y/ k( c9 g8 X7 }
3 `; c d; I! Y, U7 [4.2 插入排序的空间消耗" R) n v K7 @
6 x" G0 R$ d( Y0 W& e6 F* u( O
我们可以发现,插入排序的移动方式,需要消耗常量级的额外内存空间存储,也就是代码中的 temp,所以时间复杂度为 O(1),我们上边讲到,空间复杂度为O(1)的是原地排序算法。7 t+ R" C% }: r ]' T0 A
: ]5 |, K, C9 g, K4 Y: F" t# X4.3 插入排序的时间效率( t( u: z! q" V
* s/ a* @) _* `% R插入排序的最好情况就是不需要搬移任何数据,从头到尾寻找插入数据,每次只比较一次即可,即一组有序数据,所以最好时间复杂度为O(n)。- |/ Q. K* j+ G ^
* Q8 H# `$ E8 V. f1 C) k( D
如果一组数据正好是倒序输出,那么每次都需要比较移动所有数据,每次移动时 n,n 个数据时间复杂度为O(n2)。; q2 Z' O }2 K2 X+ |
% ^7 J" L! a2 H# P
对于插入排序的平均时间复杂度,每次插入都要移动数据,插入 n 次,所以平均时间复杂度为 O(n2)。
- t8 y8 b% Y( G. G0 \, _5 g, n, g9 D+ t3 W! y
50 j7 |3 k: r$ {& H: U; D1 E4 V% M
) p, s6 Z/ K, y1 }& }, Z& Y- `: a小结
! }' [2 Q; e# w$ x# J7 b7 I+ I6 q* w) h6 B' C/ @6 t4 Q
我们学完了今天的插入排序之后,我们回到最初的面试官问题上。插入排序和冒泡排序哪个更好呢?0 d2 R8 F. P6 i0 C' t
' D9 Z% k- o' P( f( k我们现在元素移动次数上进行分析,如果一组无序的数据通过冒泡排序排好序之后,它的交换次数是这种数据的逆序度;对于插入排序来说也是一样的,移动次数上都是原本数据的逆序度。5 i; y& g2 F8 _( b* p
: |& e- a: K6 S% ]$ q
元素的移动次数是相同的,那我们接下来看看元素的交换次数。从代码上分析可以明显看出,冒泡排序的一次交换需要三行代码,而插入排序的交换却需要一行,所以总的交换次数冒泡排序大于插入排序。8 c5 k3 D& P; T- l/ o4 B( H& Q6 N
; g: C0 C! S( @5 N+ {& }& R
有小伙伴会问,这两行的差别有那么大吗?移动一次,我们可以不计较,如果数据很多,想想下,两者的效率差别很轻易的就比较出来了。
( }. j5 k0 R' f' @1 Z; }6 R0 u3 Z% ~) b1 }
虽然冒泡排序的时间复杂度和插入排序的时间复杂度是相同的,但是我们实际使用中还是优先选择插入排序。( O# [: Q6 y7 F; q! Y
8 I& X, a/ G" t U( W
对于插入排序还是可以优化的,对了,没错,就是希尔排序,我们在这不多分开写,后期会继续更新。0 _! P' a3 T `$ w
————————————————
; `# l1 m$ T3 l版权声明:本文为CSDN博主「胡鹏程的博客」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。& K$ j, W/ }1 G( A! x' E N% M: ^
原文链接:https://blog.csdn.net/lyshark_lyshark/article/details/126792708
% L" B4 E& d3 m( S x8 z* [2 U& ]* z- _, B) A0 {- J/ l) H& J
. |* v ^2 x# t2 \ v1 e1 C |
zan
|