- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 563331 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174222
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
动画:面试官问我插入排序和冒泡排序哪个更牛逼?
; y1 }( B) @& h/ v N' b! e
% i) V" g# w# k! m0 x2 f+ }: ]1 y) d写在前边' I' @- y) V8 q
' f9 W9 w% f3 w2 b8 N q% X
) ~* n/ A) M2 }2 R1 }5 C, Z: ~
排序对于每个开发者来讲,都多多少少知道几个经典的排序算法,比如我们之前以动画形式分享的冒泡排序,也包括今天要分享的插入排序。还有一些其他经典的排序,小鹿整理的共有十种是面试常问到的,冒泡排序、插入排序、希尔排序、选择排序、归并排序、快速排序、堆排序、桶排序、计数排序、基数排序。
2 C3 T, |& l, P8 J
9 L/ U- ~! T* E$ j虽然我们基本知道了这些排序算法,但是在实际项目开发以及面试中往往出乎我们所料。在面试中,经常会被问到各种排序之间的比较;在实际项目中,往往排序的数据不是我们所练习的整数。
8 z P2 x9 U+ P0 [, k8 |) L! N. q G3 M
那么今天我们来学习一下,插入排序比我们之前讲的冒泡排序有什么区别呢?面试官问我们,我们如何回答完整呢?& c1 O4 z: }; |5 S( k# F4 r' Q |
+ ?1 }( b' `& G2 J. N( E6 M
思维导图
( R, O" i" Q' q& X) ~! K; c7 A8 q M+ v7 h& ?( R
: n* V7 E& \$ i" G* D5 }. H, b1 C Y& F
7 f* v4 v# D# y% Q) x3 B, X/ L1
8 O( L# Q, @5 U1 i6 z: j; _" E) |3 ~) S% d
如何分析一个排序算法?
9 q9 `/ r6 L! W$ v
( i/ `6 L( K2 c$ m. x0 C之前写的一篇很详细的文章。2 l& i# O! A" u% r5 P( u
7 m2 g% P0 I: W# L佩奇学编程 | 复杂度分析原来这么简单. u5 u! ^, ^) F% H' {$ X! {
& k' ^) x# u3 L7 x4 t# b. I) I2 T分析排序算法已经成为我们衡量一个算法优良的重要标准,从以下三个方面入手。, _2 N. K- x" U" L1 H0 |) `
3 {/ m* U! r( Z& i; m$ U
1.1 时间效率
, T5 r1 c' ^; F9 t# ?: \% G( }, o7 \6 S
5 @/ T3 M2 J2 k# @这里所谓的实践效率就是时间复杂度,相信大家对于时间复杂度并不陌生。8 j6 V, {3 l3 e& [3 ?
* L9 V9 l7 q4 y, g' R! I6 s8 w8 [
复杂度描述的是算法执行时间(或占用空间)与数据规模的增长关系。/ H0 Q7 ?. A5 n' n2 K: p
8 O t- P" k5 [2 _+ `7 n/ n! P' H对于时间复杂度的分析,要把最好时间复杂度、最坏时间复杂度、平均时间复杂度分析出来,分别对应了排序算法的最好排序情况、最坏排序情况以及平均排序效率。1 c% U- z; R! E, \0 Q
9 X+ V2 Q0 N- ?3 Z' B
1.2 空间消耗2 o5 M8 x. t" K5 c
; j) e' z" A5 ]: f所谓的空间消耗对应的是空间复杂度,在排序算法中需要开辟的额外内存空间是多少。如果空间复杂度为 O(1),此时该排序叫做原地排序。6 K7 L6 v2 W/ a9 r& }
W% z# `% z- |5 m9 r
注意:是额外的内存空间,存储排序数据消耗的空间不计。4 l! e2 s# E" B
# Y+ k3 L; f# G6 \" d& M1.3 稳定性
- D+ t6 _6 A$ ~) h6 y& m2 c. B3 {( w! Z
算法的稳定性虽然我们之前接触的很少,但是稳定性也是衡量一个排序算法的重要标准。什么是稳定排序呢?比如有一组有重复待排序的数据,排序前后,重复的数据顺序不变,此时该排序为稳定排序。否则,叫做不稳定排序。它在实际应用中非常重要的,今天我们就不多说,以后会慢慢分享到。5 M$ U' {% a9 ^$ M2 l
6 r8 [' f( n& g! b
24 f) T- K. L5 Q& u3 F6 V
# x8 c) A0 E. D# Q什么是插入排序?, Z" [$ T4 g; t& Y) u Y# L5 B3 q
0 ~# A1 D$ ?1 E6 G$ P* _: B
顾名思义,插入排序就是通过插入的方式来排序呗,最经典的就是打斗地主,可以将打乱的扑克牌作为未排序区间,手中已经排好序的作为排序区间。每次我们摸牌的过程,就是从未排序区间,通过插入的方式,插入到已排序区间。那么这个过程就称为插入排序。/ x# ~, ~' a: j' x# ~0 v" Y1 H6 ]
+ K& W2 \2 M% G; }% y- R9 k: S! c8 H: K+ E8 Y: S
* O4 ], }, x# B, B1 l% ?; X
3" s3 R8 K( c& Q
4 j& t, v2 L! I6 |, E- c, l' @
如何实现插入排序?- y5 [; I: P; L
2 m/ ]: f K4 O0 W! [上述插入排序的概念我们已经理解了,那么给你一组数据,如何来进行插入排序呢?: v* {4 o% Y9 \. L
O) w* P2 |; t$ x) ?
3 I: `# ?& [ ?0 o2 m+ A- ^3 `0 k
首先我们要将数据划分为两个区间,已排序区间和未排序区间。 j4 w2 q5 k. z; i7 J, ~6 r
/ Z( p3 l! Q2 F0 _! w6 \
, b0 y( r/ c1 b" l7 P5 H9 u I
v8 }% z. _5 C; r, T r5 _- U$ ^" u; L
0 e/ a1 q4 T" K1 T/ Q$ ~$ y; n我们从未排序区间取出数据和已排序区间的数据进行比较,如果小于已排序区间的数据,那我们就交换数据。. c3 [ F a( ~/ t
% P/ a( x1 c) j* p- Y' G
, i2 p; W1 x0 S* ]* s; W
) T6 x* ^# i; u
4 y* X7 J6 o2 H2 s5 F2 M+ c
% G: s/ d# l, \* e3 o如果交换到已排序区间数据不在大于插入的数据,然后将元素插入进去。$ s3 a% X! D1 A/ f6 P9 V
) G; }$ l0 ~% S9 b4 b9 o
3 ?- ?. p1 I2 Q: y% q
0 _! r- a- b# D6 R! |$ h& c& j8 [$ D+ Q1 t& z0 O. X5 P. s
( f! O8 [7 Z% b
最后我们看一下总的插入排序动画和代码实现。7 {+ v' E, r! R( `
, p7 H3 }, Q$ o- ?( T
4 ~+ n# u3 U) ~" `/ V$ z, v: y9 Y$ O' L' T
4
6 |4 B1 b9 K- y( Z. z; C- ~& H
9 w. R/ Z/ p% @% v插入排序的性能
; z1 X" \: t- c; p" o1 [$ j9 E
+ q; u( U+ e o8 V我们通过上边的对插入排序的拆分讲解和动画以及代码实现,想必面试官让你手写一个插入排序可以轻轻松松写出。但是我们掌握的插入排序知识还往往不够,我们在实际项目中,还要考虑插入排序的性能怎么样?因为才能更好的选择适当排序应用到项目中去。
; T& |" A( Y( k( X
- E: T P/ ?8 P/ N- H4.1 插入排序的稳定性
; M- j! T; n, |% t- j s3 t+ @. m0 n
再插入排序中,如果存在重复数据的话,前边的元素再插入的过程永远在第二个重复数据的前边,所以插入排序后的重复数据前后顺序不变,所以插入排序是稳定排序算法。
9 q7 U+ |4 O+ f, `) h( U! L- r
; B' e! M0 w( ^& J4.2 插入排序的空间消耗, b+ Q) ~& w! Z3 `9 @3 P7 Y+ p- L
2 `8 x& Y+ I/ c
我们可以发现,插入排序的移动方式,需要消耗常量级的额外内存空间存储,也就是代码中的 temp,所以时间复杂度为 O(1),我们上边讲到,空间复杂度为O(1)的是原地排序算法。! T/ d+ T3 y! R
8 q( R9 L! B# X4.3 插入排序的时间效率$ V/ t. ]. `3 ?/ g
3 k, u+ A' [! m- B$ ]1 w2 ?
插入排序的最好情况就是不需要搬移任何数据,从头到尾寻找插入数据,每次只比较一次即可,即一组有序数据,所以最好时间复杂度为O(n)。5 [4 ^; j3 B# f$ Q
6 M7 e+ j& {" I3 T2 y如果一组数据正好是倒序输出,那么每次都需要比较移动所有数据,每次移动时 n,n 个数据时间复杂度为O(n2)。6 b- u& R+ ?( n3 j0 i* o2 N
9 p3 N8 ^+ g2 p2 [, n. t* s6 C对于插入排序的平均时间复杂度,每次插入都要移动数据,插入 n 次,所以平均时间复杂度为 O(n2)。
8 N) S1 H% A1 @' R# ]7 A' Y' q/ k) H0 _9 q w2 t
5
0 M& |5 H8 Z% O$ W# D; |1 v
' S# v4 _; W7 J* G* B7 B8 b* K小结! O& R. {, M4 ]: u1 w5 R; t
2 } b" _/ A0 ^, V b! F
我们学完了今天的插入排序之后,我们回到最初的面试官问题上。插入排序和冒泡排序哪个更好呢?$ \, j6 b9 S; ]5 w% x$ x! w2 F
6 u; l0 z8 ~! Z4 J4 W
我们现在元素移动次数上进行分析,如果一组无序的数据通过冒泡排序排好序之后,它的交换次数是这种数据的逆序度;对于插入排序来说也是一样的,移动次数上都是原本数据的逆序度。" Z# X, e0 v$ [2 @
2 p+ }9 Z3 d5 [# ]/ x7 j" N/ s
元素的移动次数是相同的,那我们接下来看看元素的交换次数。从代码上分析可以明显看出,冒泡排序的一次交换需要三行代码,而插入排序的交换却需要一行,所以总的交换次数冒泡排序大于插入排序。- k- m" g2 q$ `7 I# B
- {4 g: m' F9 {, @- c
有小伙伴会问,这两行的差别有那么大吗?移动一次,我们可以不计较,如果数据很多,想想下,两者的效率差别很轻易的就比较出来了。+ [7 H/ ]2 w6 K+ l p
) t! c& j4 f2 y$ g* O虽然冒泡排序的时间复杂度和插入排序的时间复杂度是相同的,但是我们实际使用中还是优先选择插入排序。
( z5 w& h7 A% k/ W' K1 k4 ]% B
" \2 ]/ M4 q* Y/ n6 F& Y A对于插入排序还是可以优化的,对了,没错,就是希尔排序,我们在这不多分开写,后期会继续更新。
. i2 Z& ~4 Q# v9 S2 l; m————————————————
9 k/ v* I6 I% F, A4 H版权声明:本文为CSDN博主「胡鹏程的博客」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
* \; P& t3 W, p- a" H3 z4 W8 a3 e! R原文链接:https://blog.csdn.net/lyshark_lyshark/article/details/126792708
' z8 ?. B7 z7 B% U9 ^" S, u+ h: x! ^0 b
" p( c. a- d/ b, [/ u' ^) w9 \5 | |
zan
|