QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 1567|回复: 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 什么,图这种数据结构把你难住了?!
    9 J9 R; V8 X9 p你是不是和我一样,在学习数据结构与算法时,了解了一下图这种数据结构之后,根本不知道它的用武之地在哪里?' X* a9 ]- `& G5 M9 m0 ]* c
    在我查了资料之后,现在我可以跟你讲讲,图可以这么用!
    , z( w. N* ]$ x9 q  x8 n: x0 u+ l; |1 a$ Q3 y
    概念介绍
    + Q8 Z' g+ Q* P
    & w4 ~6 c2 T2 U9 W2 }$ J先来了解一下什么是图.
    ( [; [; [# A; H* Q' z图,是一种非线性表数据结构.
    . `" w6 F1 q; T8 A( U; }: {3 q6 M0 \那么你可能会问了,什么是线性表结构哇,我怎么区别一种数据结构是线性的,还是非线性的呢.
    & e; k/ D' m# y# [2 \5 ?哈哈,还好我机智,在这篇文章之前就写了一篇文章来介绍,如果还有疑问,楼上雅座请: [数据结构与算法]14 搞不懂线性结构,非线性结构?9 ?2 D) g7 M9 k7 W
    1 ~# x- e& i  _
    在图中元素叫做顶点( vertex ),图中的一个顶点可以和其他任意顶点建立连接关系,这种建立的关系叫做边( edge )0 }0 K7 r8 i! J
    0 p; O/ o% q1 C4 i& w
    无向图
    + a8 O2 A6 N- _1 }0 B$ X, E 1.jpg
    # O( x9 X" e1 r! R
    $ j0 @9 S/ j/ u* u/ Q# F0 H上面给出的是无向图.看到这里你可能就觉得比较疑惑,这个无向图看起来没啥呀,怎么会有这种数据结构呢?. J& ]5 s, p$ I& b  M
    不知道你是怎么想的,我刚开始学的时候就有这种疑问,这是什么神仙数据结构哇,还会有应用场景?
    ( [; A5 M# b* s. w! \/ ]- j0 O' `
    既然有疑惑,那就给个应用场景:7 Z8 a! T. X  `0 x$ [& \
    假设,现在你和我是微信好友,那是不是应该你的好友列表里面有我,我的好友里面有你,这样咱们才是好友对不对~
    9 a( Z; X4 J- b/ R那在数据库中如何表示呢?吼~这个时候无向图就登场了3 M% J! p+ a8 L- J
    你和我是微信好友,那就在咱俩之间来条线,表示咱俩之间有关系,一条线就解决了问题,真是完美至极啊
    $ Z8 b4 y+ g* l, F假设,(怎么又是假设,哈哈哈)上图中表示的就是 A,B,C,D,E,F 之间的关系,那你可能就发现问题了,有的顶点线比较多,比如 D 有四条线,有的就相对少一些,比如 B 有两条线.这些线就表示顶点的度( degree ).这个概念有啥用?
    / w/ l1 h5 M$ _2 y/ C3 Y  Q  t能一眼看出来谁的好友多!那这个功能有啥用?(好吧,这个功能好像是有点儿鸡肋,不过也算是一个应用场景6 H* V& H9 S* i4 r' w3 e& N% m
    9 W, ~4 W2 X% f- ]0 v6 i: _/ [
    有向图# a: a7 t* ]/ D+ C! o
    2.jpg
    - j: [: {/ x' |. D看到上面的无向图,基础不错的小伙伴肯定会说了,我还知道有向图呢!
    8 r. Q* L+ z; w$ x3 y& I9 F2 ~呦呵,不错,有向图就是下面这个样子:
    5 ^0 Z' n7 }& O# X' c" B# r
    , Q  Z4 U1 [. k在无向图中,咱们知道一个顶点有多少条边,就说它的度为多少.
    $ k8 H  t  F9 K) V3 ]在有向图中呢,有指向顶点的,也有从顶点指出去的,基于无向图的概念,咱们把从这个顶点指出去的边称为出度,指向该顶点的边称为入度.
    ; T& `1 _$ H8 G0 |那么有向图会应用在哪些场景呢?微信好友这个场景是不太可以了
    % J# d$ q  b% u9 |& N那么微博呢?6 B6 N8 {, C+ j9 ?4 T, K$ s0 K
    微博和微信有什么不一样呢?微信是你和我是好友,那么咱们的好友列表里一定是要有彼此的,拉黑或者删除彼此了,那就不能互相发送消息了.
    & x; q) M& g" S  N; y( X1 {但是微博呢?你关注了我,并不代表我就要关注你对吧?看到这里有没有一种豁然开朗的感觉~
    / ?$ e; X9 g# P1 K" v那么我关注了多少人就是出度,多少人关注了我就是入度.# r# M. _6 z1 _8 Z# j* A; \
    这样带入理解是不是会比较好一点儿?(我可真是个天才,哈哈哈
    - }, i2 h8 O/ e) U
    * y. \* ~0 }6 @' c) i' R! q带权图
    4 h8 ^1 @2 C! R  @5 s. {  G" d; z; z) [ 3.jpg ( l% ~( f& v# a
    看完了无向图,有向图,相信就有人说,我还见过带权图!(陈独秀给我坐下!& W( Q# U; y- J6 W7 ~
    带权图长啥样呢?就下面这个样子:# g3 r0 m$ o8 \
    ; v/ i$ e3 Z- S! [, ?8 M4 w
    懵逼了,这每条边上的数字是个什么鬼呦
    2 s/ h' x" k) e4 b别急,咱们来个场景:大家都玩 QQ 嘛?(别跟我说不玩,配合一下嘛…9 q1 f+ X8 m$ }
    玩 QQ 的话,一定知道有 QQ 空间,然后空间里面有个「谁在意我」「我在意谁」的功能,就是下图:+ F% Q! |  H: e8 _" x% x

    & o* Y1 X2 ^! A# R' k7 i7 {那么有没有好奇过呢? QQ 怎么知道我在意谁,谁在意我呢?
    8 {4 T: \' ~8 ?& `1 H+ O0 t& Q/ \  F就是通过带权图哇4 G8 T# x3 y7 |8 P- L/ M
    你访问了一个人的空间,这条边的权重就增加一点儿;别人访问了你的空间,那这条边的权重就增加一点儿;这段时间你们两个人聊天聊得比较频繁,来个小火花,顺便在你们两者之间的边权重增加一点儿.然后根据这些边的权重从大到小排序就得出了「谁在意我」「我在意谁」4 C7 X6 N- a7 B* L& f
    " i) n/ o+ N0 D% i, B/ ]. L% v
    到这里,上面的一切理解都还 OK ?
    : r0 O4 T6 t" S1 A% L那咱们继续.图是怎么表示的呢?6 u" Y0 l, T. Z3 e+ a  X6 Y
    图这种数据结构,再怎么画顶点,画边,到最后在物理结构上是怎么存储的呢?
    * U& ^8 b- o: O+ d: W8 Q- K别急,你所疑惑的,我都帮你想到了8 [$ Q% r8 s4 t8 V& r* {

    ( L1 H( u+ @6 A7 q9 B图的存储方法- j1 p2 t' d  q- N# C
      G" U8 \4 x: S, R: f6 P: ~- |
    图的存储方法主要有以下两种:
    # F7 L, q. y0 M4 R( q; p, A# V) T9 H# \" a. ?" o4 b
    邻接矩阵! D3 o6 N& X7 ?; \1 ~
    & d2 J; Z! Y: [: [  {# O# ~
    邻接矩阵的底层依赖一个二维数组.对于无向图来说,如果 i 与 j 之间有边,那就将 A[j] 和 A[j] 标记为 1 ;对于无向图来说,如果 i 指向 j ,那么 A[j] 值为 1 ,如果 j 指向 i ,那么 A[j] 值为 1 ;对于带权图来说, A[j] 存储的值就不是 1 了,而是对应的权重值.所以这是图最直观的一种存储方法.
    ) b* ~9 N5 I1 A. w/ |9 i' J3 v1 e啥,你跟我说这还不直观?该不会是没有看下图吧:
    # F1 z/ S  i# Q. M2 I 4.jpg
    : n0 r8 C. z. g) d0 N6 W) F& J& h但是你发现问题了嘛,这样看起来确实是直观了很多,但是很浪费空间有没有!比如无向图,如果 A[j] 为 1 ,那么 A[j] 肯定也是 1 ,多存储 A[j] 根本没啥必要.就像买东西,明明一块钱能买到的东西,为啥非要花两块钱?
    1 g) d9 e  y' P( R) O: S) ^0 P; x- I+ T所以如果使用邻接矩阵来表示的话,一定要清楚它的缺点.6 f, p8 j5 F* z4 U, Z
    : ~2 Q/ z4 [! H# T: O/ R
    但这并不是说,使用邻接矩阵来存储就没啥优点.这天底下哪儿有那么绝对的事情呢.
      f4 c: S9 l# Y; x: ^首先,邻接矩阵的存储方式简单,直接,所以当我们需要获取两个顶点之间的关系时,相信我没有比这种存储结构更高效的了.) e4 ~* i# a, D' a5 T! c
    还有就是使用邻接矩阵存储图的另外一个优点就是方便计算,因为可以将很多图的运算转换成矩阵之间的运算.2 h" ~) G5 o9 _& r7 y0 E

    " V& ~' M1 ^! c8 G- T' C, H. o2 `邻接表$ W4 v- D/ R# ]$ |
    . [" e/ a+ s6 E3 }( W. R1 Z
    先来看图:
    5 I# }- T6 }2 _  l, U9 \1 k 5.jpg % \8 J; H* L( O, h2 z1 G
      ^! @0 c& [1 J2 q* C
    乍一看,这不是散列表嘛!每个顶点对应一条链表,链表中存储的是与这个顶点相连接的其他顶点." C% z' f8 C& ~
    嘿嘿,直觉超棒!
    1 v6 Y' \: m: n4 \0 N" I6 o8 }
    ! R1 Z+ Z8 ^+ u9 S) x如果你对散列表熟悉的话,应该知道,在散列表中,如果链太长了,会导致冲突概率增大,复杂度也蹭的一下升高.而且吧,链表的存储方式你也知道,不是连续的,所以相对于数组来说, CPU 读取就会慢一些,相对于邻接矩阵的存储方式,在邻接表中查询两个顶点之间的关系就没那么高效了.8 s) [! d  w- g) h
    所以在实际开发中要注意遇到这种情况该如何处理,或者在刚开始的时候就直接设计好实现方式.比如可以将邻接表中的链表改为平衡二叉树,或者红黑树.* r" C( B! q2 V9 `" m
    5 c. ^+ x& ?# k8 C" S
    我觉得对于数据结构来说,没有最好的,只有最合适的~
    - h# W8 j( l4 p2 O3 s% J' \
    9 H8 b5 ~  Y" j! R: k! R# D, @$ x参考
    7 g3 O' Y0 x3 _6 \
    " t; M8 M' d' @0 @# [, d5 H极客时间—<数据结构与算法之美>
    * t. H: T+ y& K! y# n————————————————
    # X: A4 g1 C' p版权声明:本文为CSDN博主「郑璐璐」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。" L' j& B) A/ W. _
    原文链接:https://blog.csdn.net/zll_0405/article/details/105209800
    ; L. \, B0 Z- \: [; T8 Z+ L
    ) w9 |& x; V0 M' t6 L
    ' F! f- P' ^- J& W* {, {7 Z( \+ l
    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, 2026-6-10 03:06 , Processed in 0.409171 second(s), 54 queries .

    回顶部