QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 1427|回复: 0
打印 上一主题 下一主题

[数据结构与算法]16 什么,图这种数据结构把你难住了?!

[复制链接]
字体大小: 正常 放大
杨利霞        

5273

主题

82

听众

17万

积分

  • TA的每日心情
    开心
    2021-8-11 17:59
  • 签到天数: 17 天

    [LV.4]偶尔看看III

    网络挑战赛参赛者

    网络挑战赛参赛者

    自我介绍
    本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。

    群组2018美赛大象算法课程

    群组2018美赛护航培训课程

    群组2019年 数学中国站长建

    群组2019年数据分析师课程

    群组2018年大象老师国赛优

    跳转到指定楼层
    1#
    发表于 2020-4-26 15:17 |只看该作者 |倒序浏览
    |招呼Ta 关注Ta
    [数据结构与算法]16 什么,图这种数据结构把你难住了?!$ H9 ~0 K& c) |9 `
    你是不是和我一样,在学习数据结构与算法时,了解了一下图这种数据结构之后,根本不知道它的用武之地在哪里?7 [9 H. {  t7 l8 }$ s8 H1 K  T
    在我查了资料之后,现在我可以跟你讲讲,图可以这么用!, g+ J" i3 E9 M2 @' J( h
    / O+ N$ D$ R0 F5 z0 E
    概念介绍
    ! j3 m4 S3 c( j8 Q5 l" g# C, X, c
    7 s5 U! `* E2 c: H" |& n1 S# R" e先来了解一下什么是图.
    + m; m! H) \4 F6 s! I$ a图,是一种非线性表数据结构./ q. Q9 G0 n# `! y+ H6 ]; Y
    那么你可能会问了,什么是线性表结构哇,我怎么区别一种数据结构是线性的,还是非线性的呢.+ R, v7 @2 y- G" h6 Q6 I2 s  t4 S
    哈哈,还好我机智,在这篇文章之前就写了一篇文章来介绍,如果还有疑问,楼上雅座请: [数据结构与算法]14 搞不懂线性结构,非线性结构?
    6 v7 }  j8 i1 L$ |. ~( |% L: J+ I7 _2 U
    在图中元素叫做顶点( vertex ),图中的一个顶点可以和其他任意顶点建立连接关系,这种建立的关系叫做边( edge ): W* _/ |, b# Q" Q
    ' v+ K3 k: g0 k6 n' `
    无向图- Q  y2 Q0 j6 R2 ~, m+ ~, M( E
    1.jpg
    % y, I- ?$ t: G
    & J) t9 }" X  n5 _9 j上面给出的是无向图.看到这里你可能就觉得比较疑惑,这个无向图看起来没啥呀,怎么会有这种数据结构呢?" C* a  q9 C) {* ^: w4 q5 A; \
    不知道你是怎么想的,我刚开始学的时候就有这种疑问,这是什么神仙数据结构哇,还会有应用场景?
    6 @% {: T) ~0 N* k# p
    : ^3 O& ]; q  O# [$ R既然有疑惑,那就给个应用场景:
    + U+ i1 r' @- E; K* e* C5 p7 M+ a9 M假设,现在你和我是微信好友,那是不是应该你的好友列表里面有我,我的好友里面有你,这样咱们才是好友对不对~- x* ~9 ^+ [' z: z2 M# ^
    那在数据库中如何表示呢?吼~这个时候无向图就登场了
    2 M2 N" j, U( x* C你和我是微信好友,那就在咱俩之间来条线,表示咱俩之间有关系,一条线就解决了问题,真是完美至极啊! k. o: \6 h: J4 B; o
    假设,(怎么又是假设,哈哈哈)上图中表示的就是 A,B,C,D,E,F 之间的关系,那你可能就发现问题了,有的顶点线比较多,比如 D 有四条线,有的就相对少一些,比如 B 有两条线.这些线就表示顶点的度( degree ).这个概念有啥用?. v4 }$ G" o2 h- g" B0 d
    能一眼看出来谁的好友多!那这个功能有啥用?(好吧,这个功能好像是有点儿鸡肋,不过也算是一个应用场景  s( B* w9 W1 R  R
    $ q" O3 n$ Z2 {
    有向图: j( @: w) p" Q' p3 _
    2.jpg 4 D4 X7 B8 g1 c2 e
    看到上面的无向图,基础不错的小伙伴肯定会说了,我还知道有向图呢!% Y8 l1 a+ T  u5 v% l. J. ^
    呦呵,不错,有向图就是下面这个样子:
    : [0 l& I0 v+ T% T( d& }3 A
    * ?& @7 d. p1 [0 Q$ o5 a7 R在无向图中,咱们知道一个顶点有多少条边,就说它的度为多少.
    , V( ~, S2 d5 u在有向图中呢,有指向顶点的,也有从顶点指出去的,基于无向图的概念,咱们把从这个顶点指出去的边称为出度,指向该顶点的边称为入度.2 X6 p/ N+ {/ A' s  j! r- p2 i
    那么有向图会应用在哪些场景呢?微信好友这个场景是不太可以了$ P9 h- A8 o/ [$ y1 q
    那么微博呢?( c% y# n+ h$ V0 M7 P) f
    微博和微信有什么不一样呢?微信是你和我是好友,那么咱们的好友列表里一定是要有彼此的,拉黑或者删除彼此了,那就不能互相发送消息了.
    , P4 q, V  h- Y$ j. j但是微博呢?你关注了我,并不代表我就要关注你对吧?看到这里有没有一种豁然开朗的感觉~( @% Z( v. z! D/ \
    那么我关注了多少人就是出度,多少人关注了我就是入度.# A* R  F0 w+ k; K: J' B
    这样带入理解是不是会比较好一点儿?(我可真是个天才,哈哈哈
    , ~8 P, l* T& H) e9 N+ x- q0 k7 D
    & }2 w1 m5 [; [3 s$ T' n带权图; U/ D/ x( r3 c9 k- ?! s2 H
    3.jpg
    1 M. B9 c. I4 e) l# i看完了无向图,有向图,相信就有人说,我还见过带权图!(陈独秀给我坐下!
    6 w: v6 t8 U7 G* m9 O7 i3 F4 S带权图长啥样呢?就下面这个样子:
    9 L( e* _0 O. a( k. d* g, o2 j# K4 V. _. L
    懵逼了,这每条边上的数字是个什么鬼呦
    8 r9 k( ~0 v7 }2 ?. v- D别急,咱们来个场景:大家都玩 QQ 嘛?(别跟我说不玩,配合一下嘛…; f- Y5 v  `, x* `; k4 A
    玩 QQ 的话,一定知道有 QQ 空间,然后空间里面有个「谁在意我」「我在意谁」的功能,就是下图:  k3 m- \2 Q& L6 C# ~
    3 \9 g( l, v) e- \# F" b' ^
    那么有没有好奇过呢? QQ 怎么知道我在意谁,谁在意我呢?+ H) @6 c/ _$ ^& d; h  @$ u5 d
    就是通过带权图哇& L0 p! J1 m( G5 y7 D
    你访问了一个人的空间,这条边的权重就增加一点儿;别人访问了你的空间,那这条边的权重就增加一点儿;这段时间你们两个人聊天聊得比较频繁,来个小火花,顺便在你们两者之间的边权重增加一点儿.然后根据这些边的权重从大到小排序就得出了「谁在意我」「我在意谁」) \) T6 a! v/ z# F, X
    / J4 ~0 B( g6 Q% @7 k% _- w, Y
    到这里,上面的一切理解都还 OK ?8 d! {6 N5 z3 h  x$ l
    那咱们继续.图是怎么表示的呢?1 G8 `" P1 y% ]3 O. [' |
    图这种数据结构,再怎么画顶点,画边,到最后在物理结构上是怎么存储的呢?( U4 ?  S$ u, Y; m/ s
    别急,你所疑惑的,我都帮你想到了
    7 ]! O" n  c/ j5 C  v$ \# S3 \/ Z* P7 m0 M
    图的存储方法
    % S$ c0 s4 Z, m7 c% y/ ^" P5 h5 V  }" ~9 F
    图的存储方法主要有以下两种:" {8 ]/ A. z+ u! ^' f+ A4 W6 h

    ' c" Z" D$ a6 ^5 |) i! _3 T* I6 v& a邻接矩阵( [) E& y- }# J( m2 k; ?* W* O
    $ ?4 l9 n* D5 z6 d* I
    邻接矩阵的底层依赖一个二维数组.对于无向图来说,如果 i 与 j 之间有边,那就将 A[j] 和 A[j] 标记为 1 ;对于无向图来说,如果 i 指向 j ,那么 A[j] 值为 1 ,如果 j 指向 i ,那么 A[j] 值为 1 ;对于带权图来说, A[j] 存储的值就不是 1 了,而是对应的权重值.所以这是图最直观的一种存储方法.$ P- d& G# X8 r! k$ Y
    啥,你跟我说这还不直观?该不会是没有看下图吧:
    0 {2 d4 s4 L* A0 |* h) l, E, r4 s 4.jpg
    % [7 V' e& W: w% o1 ]但是你发现问题了嘛,这样看起来确实是直观了很多,但是很浪费空间有没有!比如无向图,如果 A[j] 为 1 ,那么 A[j] 肯定也是 1 ,多存储 A[j] 根本没啥必要.就像买东西,明明一块钱能买到的东西,为啥非要花两块钱?! {% a! s- I8 N1 n: Q! r# ~
    所以如果使用邻接矩阵来表示的话,一定要清楚它的缺点.
    2 p/ t4 B* e# K+ H% y) L* R! ]+ G3 r3 a# Q: C+ h
    但这并不是说,使用邻接矩阵来存储就没啥优点.这天底下哪儿有那么绝对的事情呢.; B3 a- o& f! E! ]& p6 i; s8 v; J
    首先,邻接矩阵的存储方式简单,直接,所以当我们需要获取两个顶点之间的关系时,相信我没有比这种存储结构更高效的了.( J% H& V- c, w; N* p
    还有就是使用邻接矩阵存储图的另外一个优点就是方便计算,因为可以将很多图的运算转换成矩阵之间的运算./ a1 a! m2 A/ Q
    + z8 p7 N! g6 h1 s
    邻接表8 L# v; \/ s' T, F) n/ H; s4 F
    ! ]4 A) {* O6 u' a4 o
    先来看图:
    ' s- ~% c, R/ M% R; | 5.jpg
    9 K- I3 a& u# Y* t6 w* ~2 }  i, R3 O: l
    乍一看,这不是散列表嘛!每个顶点对应一条链表,链表中存储的是与这个顶点相连接的其他顶点.1 T" c! z) v6 p3 l8 w+ w. w
    嘿嘿,直觉超棒!2 n; {1 U. J2 a# J' p

    / c" S# \* G* ^5 m+ x! f; \/ ^如果你对散列表熟悉的话,应该知道,在散列表中,如果链太长了,会导致冲突概率增大,复杂度也蹭的一下升高.而且吧,链表的存储方式你也知道,不是连续的,所以相对于数组来说, CPU 读取就会慢一些,相对于邻接矩阵的存储方式,在邻接表中查询两个顶点之间的关系就没那么高效了.2 Z" D3 s' }  d, p- V! @# A4 u
    所以在实际开发中要注意遇到这种情况该如何处理,或者在刚开始的时候就直接设计好实现方式.比如可以将邻接表中的链表改为平衡二叉树,或者红黑树.
    % H, T5 _1 V+ F6 P. _, W$ C2 |) D. H/ W/ {! i  ?
    我觉得对于数据结构来说,没有最好的,只有最合适的~
    9 ]) R0 l3 F$ }1 X/ C1 e$ U  G
    : Z( N" r7 d! j( b4 ^参考0 Q" w7 Z+ G4 |# L* ~

    " F! x8 D& m3 \: {极客时间—<数据结构与算法之美>& f1 v0 H8 t5 l
    ————————————————- P4 m+ K9 M: I& G) y' N
    版权声明:本文为CSDN博主「郑璐璐」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。) m& E. D+ M' k* u
    原文链接:https://blog.csdn.net/zll_0405/article/details/105209800
    7 R) S: ]5 `' f6 r7 L9 D; Y. `3 W5 O
    & D# m' G8 t& e) y
    0 q7 X% ?- I8 h1 e
    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2025-9-22 20:31 , Processed in 0.995549 second(s), 53 queries .

    回顶部