- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 563401 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174243
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
[数据结构与算法]16 什么,图这种数据结构把你难住了?!( |1 m& ]* i- D: c5 A- k
你是不是和我一样,在学习数据结构与算法时,了解了一下图这种数据结构之后,根本不知道它的用武之地在哪里?
) D! B: F O3 s D F& [9 ^在我查了资料之后,现在我可以跟你讲讲,图可以这么用!
$ N1 }, a& s5 A3 w, [" M: b
7 h, d: K9 o, e5 |- S概念介绍
6 s3 J% V/ j$ v( `7 k: U; d& O Q1 Y- e- O
先来了解一下什么是图., z7 @0 A5 N/ Y7 e6 @& a; A) \
图,是一种非线性表数据结构.* K( D: u! z/ f. L4 K7 d' ^5 N
那么你可能会问了,什么是线性表结构哇,我怎么区别一种数据结构是线性的,还是非线性的呢.8 a* E% ^- M3 m# n% L2 w$ C, I
哈哈,还好我机智,在这篇文章之前就写了一篇文章来介绍,如果还有疑问,楼上雅座请: [数据结构与算法]14 搞不懂线性结构,非线性结构?8 E3 V$ z( z# ^, P. w* d5 c; W
2 R3 G) f& V1 Q6 b9 h% C- a2 ?
在图中元素叫做顶点( vertex ),图中的一个顶点可以和其他任意顶点建立连接关系,这种建立的关系叫做边( edge )
" D) G1 G: Y5 U2 G( P
+ e! S0 O7 |1 e v: C) a无向图! l- {9 _5 K: ?* d: W* L9 Q6 [2 t: W
2 y- ~2 h1 b! R7 B2 o% O) y
- x7 _5 R! y' Y) L上面给出的是无向图.看到这里你可能就觉得比较疑惑,这个无向图看起来没啥呀,怎么会有这种数据结构呢?; n. P! u8 o" a8 F
不知道你是怎么想的,我刚开始学的时候就有这种疑问,这是什么神仙数据结构哇,还会有应用场景?
: r% I( U0 N' {) t! W
( y6 b1 m( I1 \% U4 Z既然有疑惑,那就给个应用场景:8 L0 w, c+ x5 k2 i7 l- w2 ]
假设,现在你和我是微信好友,那是不是应该你的好友列表里面有我,我的好友里面有你,这样咱们才是好友对不对~
' a ?. H7 H+ e; C- Z那在数据库中如何表示呢?吼~这个时候无向图就登场了5 p0 f$ F: P7 l* T
你和我是微信好友,那就在咱俩之间来条线,表示咱俩之间有关系,一条线就解决了问题,真是完美至极啊4 B0 j/ e. i9 w! o
假设,(怎么又是假设,哈哈哈)上图中表示的就是 A,B,C,D,E,F 之间的关系,那你可能就发现问题了,有的顶点线比较多,比如 D 有四条线,有的就相对少一些,比如 B 有两条线.这些线就表示顶点的度( degree ).这个概念有啥用?
8 r" }0 ~) J3 _5 z, ]( w( i能一眼看出来谁的好友多!那这个功能有啥用?(好吧,这个功能好像是有点儿鸡肋,不过也算是一个应用场景# O$ |8 p1 m/ Q" d6 Q: f
% @/ }- Z7 L/ R% l- a, S
有向图6 N2 G; s: s, J# D% h
& w9 ?( ?. s) u4 @# {/ {* g/ U
看到上面的无向图,基础不错的小伙伴肯定会说了,我还知道有向图呢!
/ S, a6 h+ E4 @& c2 y; Z呦呵,不错,有向图就是下面这个样子:, @4 q1 K! ~& F- ?
! z4 F( l9 }7 d" ^9 H! c3 `
在无向图中,咱们知道一个顶点有多少条边,就说它的度为多少.
8 S0 k( A+ V. e9 R" P( o在有向图中呢,有指向顶点的,也有从顶点指出去的,基于无向图的概念,咱们把从这个顶点指出去的边称为出度,指向该顶点的边称为入度.4 _( q5 _, N3 u7 y O# E
那么有向图会应用在哪些场景呢?微信好友这个场景是不太可以了/ V5 J: K' E* @% _
那么微博呢?
8 b* s8 r- n4 k) e& C5 o% O微博和微信有什么不一样呢?微信是你和我是好友,那么咱们的好友列表里一定是要有彼此的,拉黑或者删除彼此了,那就不能互相发送消息了.
+ y& c$ z+ I0 z+ K但是微博呢?你关注了我,并不代表我就要关注你对吧?看到这里有没有一种豁然开朗的感觉~/ H9 Q3 s2 F2 l) @+ b$ G
那么我关注了多少人就是出度,多少人关注了我就是入度.
$ p5 V# ~; n5 T这样带入理解是不是会比较好一点儿?(我可真是个天才,哈哈哈
; X3 N" m9 k9 P1 V" H7 f. O7 ?7 @& E4 ~* E9 @! _9 G& x; j" i
带权图
- v( V3 ~- V0 w& }. B3 F1 i
* P. a% C9 c6 r/ W/ u
看完了无向图,有向图,相信就有人说,我还见过带权图!(陈独秀给我坐下!4 |. v( ^! I* y
带权图长啥样呢?就下面这个样子:
: ?$ S e8 K) g( s" a( W
2 Y, N: I0 x: w! c. E懵逼了,这每条边上的数字是个什么鬼呦5 t1 ?# ]; ~, R
别急,咱们来个场景:大家都玩 QQ 嘛?(别跟我说不玩,配合一下嘛…: Z7 s3 I2 |3 |' m0 c9 v
玩 QQ 的话,一定知道有 QQ 空间,然后空间里面有个「谁在意我」「我在意谁」的功能,就是下图:+ V; ~4 C2 H1 a9 k6 U. _0 H2 _
* r( g' Y. T) q" q W9 `那么有没有好奇过呢? QQ 怎么知道我在意谁,谁在意我呢?7 {1 H! e% V+ f7 n
就是通过带权图哇: h0 E3 W2 g' }. S
你访问了一个人的空间,这条边的权重就增加一点儿;别人访问了你的空间,那这条边的权重就增加一点儿;这段时间你们两个人聊天聊得比较频繁,来个小火花,顺便在你们两者之间的边权重增加一点儿.然后根据这些边的权重从大到小排序就得出了「谁在意我」「我在意谁」
9 B$ r; O. x3 d/ n+ g
6 X; l$ v5 n, \# ^: o# V/ x/ d到这里,上面的一切理解都还 OK ?% b8 m6 L4 v8 j2 l. d$ u6 H
那咱们继续.图是怎么表示的呢?
) V% s3 s7 p8 N/ }( t% h" W图这种数据结构,再怎么画顶点,画边,到最后在物理结构上是怎么存储的呢?, _3 p+ @$ X0 I' a. y
别急,你所疑惑的,我都帮你想到了
2 x0 c. k5 F d! v8 g7 ]4 Z
5 q- O5 G+ o1 ^ C$ L图的存储方法, c- w" P+ ~4 k1 Z: F$ |
! u5 }* N" B# |# ~7 ?9 E图的存储方法主要有以下两种:. f- m7 U. a& z/ n+ y' a6 k
) g' G/ {: M: W4 k/ D邻接矩阵
% J ]/ R" c; \: a
* s# u( o) j) R: D; {$ i$ i2 n' q$ V邻接矩阵的底层依赖一个二维数组.对于无向图来说,如果 i 与 j 之间有边,那就将 A[j] 和 A[j] 标记为 1 ;对于无向图来说,如果 i 指向 j ,那么 A[j] 值为 1 ,如果 j 指向 i ,那么 A[j] 值为 1 ;对于带权图来说, A[j] 存储的值就不是 1 了,而是对应的权重值.所以这是图最直观的一种存储方法.
% T- Z* @ s+ @/ I g: F* R, W5 ~& Y啥,你跟我说这还不直观?该不会是没有看下图吧:% a$ U# \+ Y' [
6 [( X! i. A& T* B" e6 m1 p但是你发现问题了嘛,这样看起来确实是直观了很多,但是很浪费空间有没有!比如无向图,如果 A[j] 为 1 ,那么 A[j] 肯定也是 1 ,多存储 A[j] 根本没啥必要.就像买东西,明明一块钱能买到的东西,为啥非要花两块钱?8 d% k% E6 h. d4 d/ t4 D0 a
所以如果使用邻接矩阵来表示的话,一定要清楚它的缺点.
9 {- w; o& s8 g2 U! Z# F4 \0 l& {9 w( A3 u
但这并不是说,使用邻接矩阵来存储就没啥优点.这天底下哪儿有那么绝对的事情呢.7 D. f% ~, K! Z2 o; m) i9 Q
首先,邻接矩阵的存储方式简单,直接,所以当我们需要获取两个顶点之间的关系时,相信我没有比这种存储结构更高效的了.
* v& \3 a0 }( ~. C2 i7 o$ Z& H7 X还有就是使用邻接矩阵存储图的另外一个优点就是方便计算,因为可以将很多图的运算转换成矩阵之间的运算.
5 E4 v; L/ t a- j4 ?& }
4 z9 i. O; E1 N& r邻接表5 Q% w0 ?- @2 |8 c3 n3 O
- A0 N" P* C1 c, }4 t8 b
先来看图:5 q" k. p5 {& T1 Y8 T
) g0 p( ]5 k6 S- [" r/ a" }% k
8 }* L$ u& U6 U6 a9 s
乍一看,这不是散列表嘛!每个顶点对应一条链表,链表中存储的是与这个顶点相连接的其他顶点.
% \) g. k3 m( T1 c! M* t0 W6 `嘿嘿,直觉超棒!
# w) j3 F( Z) |$ F% F4 R. A
& x+ @2 a# T" ?. q如果你对散列表熟悉的话,应该知道,在散列表中,如果链太长了,会导致冲突概率增大,复杂度也蹭的一下升高.而且吧,链表的存储方式你也知道,不是连续的,所以相对于数组来说, CPU 读取就会慢一些,相对于邻接矩阵的存储方式,在邻接表中查询两个顶点之间的关系就没那么高效了.5 [# }) x1 B+ a9 }/ ~+ Y
所以在实际开发中要注意遇到这种情况该如何处理,或者在刚开始的时候就直接设计好实现方式.比如可以将邻接表中的链表改为平衡二叉树,或者红黑树.( T) y/ _& ?7 i Z
7 l) W+ I. Z. x3 n! e
我觉得对于数据结构来说,没有最好的,只有最合适的~" Z: J$ I- T* l! c% z
- `4 V+ O% q" W' p6 n) y
参考
1 ]- I/ @6 a1 _5 o8 m/ K, Y: J. F7 O
极客时间—<数据结构与算法之美>
: n* k& f& y3 U/ ^' D2 k% k3 Y) \5 E————————————————
$ q1 A' b& V; s' i版权声明:本文为CSDN博主「郑璐璐」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。* Y2 J1 l# u. Y2 x3 W) w, J3 Q
原文链接:https://blog.csdn.net/zll_0405/article/details/1052098005 M- l1 W9 W+ e; Q
4 L! P% n4 N Y* P4 [1 g
0 o/ [! o3 ]- q/ C) E- n' p2 u |
zan
|