- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 569615 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 176107
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
动画:面试官问我插入排序和冒泡排序哪个更牛逼?: _- `0 s4 }# F; `
, s+ F8 A. e3 `! j写在前边0 `/ A5 V$ b, N- J% Q; _# J
|0 R, A9 B# x- J, N* P" C
) W2 V1 q/ _5 ]9 n# R4 T2 p
排序对于每个开发者来讲,都多多少少知道几个经典的排序算法,比如我们之前以动画形式分享的冒泡排序,也包括今天要分享的插入排序。还有一些其他经典的排序,小鹿整理的共有十种是面试常问到的,冒泡排序、插入排序、希尔排序、选择排序、归并排序、快速排序、堆排序、桶排序、计数排序、基数排序。
- a% R1 [1 w! }& f+ Q
) a8 v. V/ O% M0 [+ x5 v3 L" z虽然我们基本知道了这些排序算法,但是在实际项目开发以及面试中往往出乎我们所料。在面试中,经常会被问到各种排序之间的比较;在实际项目中,往往排序的数据不是我们所练习的整数。
% l. z' M r8 ] s- i9 A! ?" z- W0 A+ `, \ @( T$ E
那么今天我们来学习一下,插入排序比我们之前讲的冒泡排序有什么区别呢?面试官问我们,我们如何回答完整呢?. ]& c) z# h' t) X& \ w
' q+ k; x: l1 q" X% k. M; Z& |, T
思维导图
+ Q6 ?+ H+ q) y. B1 z) L* t, c& Q$ E1 G: m- D# K" E( D
2 V7 ^3 t- f7 X/ ?( }9 K
1 T/ d A& U# t2 s7 J
) C" _3 q3 n& o1 b
16 J- Q9 l# G4 E: a( X% Q! C
2 B% o i' {$ @6 U; B# c) t
如何分析一个排序算法?
: T+ |' m# r+ g1 o% ^4 ?$ u5 ?
" ?8 b, Y8 y3 ^之前写的一篇很详细的文章。
; i6 V/ v6 x3 G9 f/ k- e+ b9 `" W; D, _; M1 r
佩奇学编程 | 复杂度分析原来这么简单
% O8 V( Z3 _; G/ ^7 z+ ~" |
9 S+ J# `4 ~: s分析排序算法已经成为我们衡量一个算法优良的重要标准,从以下三个方面入手。
6 H* b9 Z$ M0 B) v3 O
. V$ S$ e3 d) `% q2 A6 |1.1 时间效率
1 n6 f- k H* Q+ _% e7 m
* C5 p6 a7 P1 y1 Y; h这里所谓的实践效率就是时间复杂度,相信大家对于时间复杂度并不陌生。9 ~8 b1 w' r6 u, A- c& t. r( b
- v! B3 k( {# f: o复杂度描述的是算法执行时间(或占用空间)与数据规模的增长关系。
8 E; z9 g1 e5 p* R1 z# V- Z1 Q/ L) `& s( M! P s6 m L
对于时间复杂度的分析,要把最好时间复杂度、最坏时间复杂度、平均时间复杂度分析出来,分别对应了排序算法的最好排序情况、最坏排序情况以及平均排序效率。
0 P5 t" t, \! P. z5 _1 Q4 @+ T+ d( u* i; O& ^) D3 ?
1.2 空间消耗# O" t# y9 J# O; U
, }$ \6 F j& x1 u: g: w所谓的空间消耗对应的是空间复杂度,在排序算法中需要开辟的额外内存空间是多少。如果空间复杂度为 O(1),此时该排序叫做原地排序。* W0 _. M4 {+ _* `$ h% b
; ^: a+ z/ ^" {7 u* c注意:是额外的内存空间,存储排序数据消耗的空间不计。4 C9 N3 i& O6 @ `% a/ N/ D4 r
9 M/ z& m. g0 R0 I( a7 F
1.3 稳定性4 T; Z1 ~( a" d4 M1 `1 H
2 }' w- k* h+ }算法的稳定性虽然我们之前接触的很少,但是稳定性也是衡量一个排序算法的重要标准。什么是稳定排序呢?比如有一组有重复待排序的数据,排序前后,重复的数据顺序不变,此时该排序为稳定排序。否则,叫做不稳定排序。它在实际应用中非常重要的,今天我们就不多说,以后会慢慢分享到。4 Q- {0 E* C8 X. \$ `; `! ]
' S4 j( u; ~2 W2 a2
9 e; l$ Q. k. y( |" V, K* E/ I; R1 s: g, c" F6 e) M$ M
什么是插入排序?: F( Z) e P; q6 Q* H5 d6 T( s
5 x* \% Q5 O/ I0 e7 O3 [顾名思义,插入排序就是通过插入的方式来排序呗,最经典的就是打斗地主,可以将打乱的扑克牌作为未排序区间,手中已经排好序的作为排序区间。每次我们摸牌的过程,就是从未排序区间,通过插入的方式,插入到已排序区间。那么这个过程就称为插入排序。 ~8 M: I% R/ J3 r
$ Z# Y1 v- l% s) S8 w; c/ k% k, f9 A* H
+ K: r$ \; @: y( q
3# [: _; a% D4 K" Q3 {
5 Z! Y2 V: {: \# p如何实现插入排序?- c+ s; [6 K5 |4 h
' ~7 ^2 {8 I" a% H6 j7 K上述插入排序的概念我们已经理解了,那么给你一组数据,如何来进行插入排序呢?
/ I, y# A3 M$ t7 K) ^3 i
3 i8 C. s. d# E# ~7 [/ Z/ |, \6 D5 g/ w t6 W! }4 F. v
9 V4 J7 W; }+ x* J6 N% y+ l E首先我们要将数据划分为两个区间,已排序区间和未排序区间。* B6 j" D0 T) A% x& E4 \
: {) X. M, M2 e( n/ C/ ?- t9 r$ {1 s: w
5 P7 _% F9 p- ?7 I0 ?, I: b
# h" i B% l; H$ p6 v: {3 e3 }* X! f& u( j
我们从未排序区间取出数据和已排序区间的数据进行比较,如果小于已排序区间的数据,那我们就交换数据。7 d. u% ^# G7 `" r
2 a( v# F2 F% H6 Y7 Y2 A2 n& J) A- ~% v0 `- l
3 L' b# K' l1 F8 T: Y# e- U8 n; P
" |; B$ K3 H. Q" d2 Y* q! l( M( K' y" q( W+ u9 x, E# r
如果交换到已排序区间数据不在大于插入的数据,然后将元素插入进去。
9 ]$ Q/ |) Y! M6 n& k1 ^$ d& ^3 R. p% X% t3 J F, ?
, S- @0 G: w0 T, I9 b$ `
( K, V! K: `) O1 W/ u
+ l& j; ^/ a; n7 ?" V' O( m) j4 z6 d/ r, Q9 a/ V
最后我们看一下总的插入排序动画和代码实现。
; g8 U' ~; I- x! n
0 `6 M8 W( h _! c2 V& m: }' O c* a5 K# v
, a- f* _* d! n
4
( c& ^+ ~3 d" R; W; x9 M) D# ]# Q& R
0 C! a7 l0 ^+ y插入排序的性能
: R' U6 P/ l K1 _. ]
" C# q( q$ E7 r7 |我们通过上边的对插入排序的拆分讲解和动画以及代码实现,想必面试官让你手写一个插入排序可以轻轻松松写出。但是我们掌握的插入排序知识还往往不够,我们在实际项目中,还要考虑插入排序的性能怎么样?因为才能更好的选择适当排序应用到项目中去。% k; ^( J8 I1 j' X. b% Z5 t, M
: O/ }( e% ]1 y F* j- j& e0 G5 ~4.1 插入排序的稳定性
* j9 e W' s' v! P
, U: h W+ S/ o. P再插入排序中,如果存在重复数据的话,前边的元素再插入的过程永远在第二个重复数据的前边,所以插入排序后的重复数据前后顺序不变,所以插入排序是稳定排序算法。
2 h& W+ l' Q$ D, x. _: Y% ]# c1 w- F2 p& ~# Y5 E4 d+ ^8 t2 Y
4.2 插入排序的空间消耗
9 W9 W1 l) n4 |0 ]0 ^( n+ c: |& Y1 E+ d# ]% [1 E8 A
我们可以发现,插入排序的移动方式,需要消耗常量级的额外内存空间存储,也就是代码中的 temp,所以时间复杂度为 O(1),我们上边讲到,空间复杂度为O(1)的是原地排序算法。! H" p# u* J0 b7 u4 D
, Y! ^; h- q7 s4 I' Z
4.3 插入排序的时间效率
5 M+ i D/ n- s* j) H+ t- J. S
- q9 T. I+ P) K8 N: x, ^插入排序的最好情况就是不需要搬移任何数据,从头到尾寻找插入数据,每次只比较一次即可,即一组有序数据,所以最好时间复杂度为O(n)。
5 K& d: s* V( x/ l
( h7 y) H# n+ R1 U如果一组数据正好是倒序输出,那么每次都需要比较移动所有数据,每次移动时 n,n 个数据时间复杂度为O(n2)。6 a, X* F) {$ L* g+ J
) a* g8 q/ E5 n, @' Q# z3 [
对于插入排序的平均时间复杂度,每次插入都要移动数据,插入 n 次,所以平均时间复杂度为 O(n2)。
2 X. Z& C: A4 i; n) l+ v6 E* b$ d' {, k% A' t
5
' K- H# X% `: n
! m& Y$ k. @3 t) X3 a小结
/ N5 H7 S0 M! E% R) O5 w" H) `. A
我们学完了今天的插入排序之后,我们回到最初的面试官问题上。插入排序和冒泡排序哪个更好呢?. B# Y* t6 a: h- A) K
( s* U3 u3 h |/ F2 U
我们现在元素移动次数上进行分析,如果一组无序的数据通过冒泡排序排好序之后,它的交换次数是这种数据的逆序度;对于插入排序来说也是一样的,移动次数上都是原本数据的逆序度。
2 \8 d- z X' Q5 E0 F& ]: j
: }. b0 t F8 W8 O元素的移动次数是相同的,那我们接下来看看元素的交换次数。从代码上分析可以明显看出,冒泡排序的一次交换需要三行代码,而插入排序的交换却需要一行,所以总的交换次数冒泡排序大于插入排序。! }* i E! L. S- ?" N
* k( R8 M$ _; } q有小伙伴会问,这两行的差别有那么大吗?移动一次,我们可以不计较,如果数据很多,想想下,两者的效率差别很轻易的就比较出来了。
' Q* c/ A% k2 h- r5 j8 x$ Z3 [# d; ]1 X8 ?7 A) l- G; W( Q" {
虽然冒泡排序的时间复杂度和插入排序的时间复杂度是相同的,但是我们实际使用中还是优先选择插入排序。; i7 E5 E! Z# \$ u' x! L
4 @7 V2 W0 Z- W9 q6 ~6 R! r; e8 G! r5 G对于插入排序还是可以优化的,对了,没错,就是希尔排序,我们在这不多分开写,后期会继续更新。
% E! r( ?4 _( _& y————————————————
, L% }( y: r/ v% ^% o版权声明:本文为CSDN博主「胡鹏程的博客」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。& G! t( H% x8 b' k1 i
原文链接:https://blog.csdn.net/lyshark_lyshark/article/details/126792708
9 ]; |+ w' N0 E7 u3 Z, p! D4 \# n9 i( h/ `
+ d; J6 b" R0 h4 C' g5 Y
|
zan
|