zoukankan      html  css  js  c++  java
  • 第六章学习小结

    一、本章学习小结

    本章学习了图这一复杂的非线性数据结构,图包括有向图和无向图,有向图中又包含始点和终点,弧尾和弧头的概念。两者的本质区别应该是有无序。重点学习了DFS算法和BFS算法实现图的遍历,理解了迪杰斯特拉算法的逻辑思想。

    1、图的基本术语(顶点数目为n,边数目为e)

    子图、稀疏图和稠密图、权和网、邻接点、度、入度和出度、路径和路径长度、回路或环、连通、连通图和连通分量、强连通图和强连通分量、有向树和生成森林。

     有向完全图:具有n(n-1)条边的有向图。         无向完全图:具有n(n-1)/2条边的无向图。      

    有向图:度=入度+出度。                                 无向图:无入度出度之分。

    路径长度:一条路径上经过的边或弧的数目。

    连通分量:无向图中的极大连通子图 。(对于连通图,其连通分量是其本身)

    有向图中的极大连通子图称作有向图的强连通分量。

    连通图的生成树:一个极小的连通子图包含图中全部顶点,但只有足以构成一棵树的n-1条边。

    有向树:有一个顶点的入度为0,其余顶点的入度均为1的有向图。

    2、图的存储结构

    邻接矩阵表示法:适用于稠密图,时间和空间复杂度均为O(n^2)。

     1 #define MaxInt    //表示极大值 
     2 #define MVNum 100    //最大顶点数 
     3 typedef char VerTexType;    //顶点的数据类型 
     4 typedef int ArcType;     //边的权值类型 
     5 typedef struct
     6 {
     7     VerTexType vexs[MVNum];   //顶点表 
     8     ArcType arcs[MVNum][MVNum];    //邻接矩阵 
     9     int vexnum, arcnum;   //图的当前点数和边数 
    10 }AMGraph;

    邻接表表示法:适用于稀疏图,时间和空间复杂度均为O(n+e)。

     1 #define MVNum 100        //最大顶点数 
     2 typedef struct ArcNode   //邻接点的结构 
     3 {
     4     int adjvex;        //该边所指向的顶点的位置
     5     struct ArcNode *nextarc;     //指向下一条边的指针
     6     OtherInfo info;        //和边相关的信息,例如权值 
     7 }ArcNode;
     8 typedef struct VNode   //顶点的结构 
     9 {
    10     VerTexType data;     //顶点信息 
    11     ArcNode *firstarc;    //指向第一条依附该顶点的弧 
    12 }VNode, AdjList[MVNum];
    13 typedef struct
    14 {
    15     AdjList vertices;
    16     int vexnum, arcnum;     //顶点数和边数 
    17 }ALGraph;

    还有十字链表(有向图)和邻接多重表(无向图)。

    3、图的遍历

    深度优先遍历(DFS算法):类似树的先序遍历,借助栈结构实现运用递归

     1 bool visited[MVNum];      //访问标志数组, 其初值为"false" 
     2 //连通图 
     3 void DFS(Graph G, int v)  
     4 {
     5     cout<<v;   visited[v]=true; 
     6     //访问第v个顶点,并置访问标志数组相应分扯值为true 
     7     for(w=FirstAdjVex(G,v); w>=O; w=NextAdjVex(G,v,w)) 
     8     //依次检查v的所有邻接点w,FirstAdjVex(G,v)表示v的第一个邻接点 
     9     //NextAdjVex(G,v,w)表示v相对于w的下一个邻接点,w≧0表示存在邻接点
    10         if(!visited[w])     DFS(G,w);   
    11         //对v的尚未访问的邻接顶点w递归调用 DFS 
    12 }
    13 //非连通图 
    14 void DFSTraverse(Graph G)   
    15 {
    16     for(v=0; v<G.vexnum; ++v)   
    17         visited[v]=false;    //访问标志数组初始化
    18     for(v=0; v<G.vexnum; ++v)   //循环调用算法6.3
    19         if(!visited[v])     DFS(G, v);    //对尚未访问的顶点调用DFS
    20 }

    广度优先遍历(BFS算法):类似树的层次遍历,借助队列结构

     1 void BFS{Graph G, int v)   //连通图 
     2 {
     3     cout<<v;    
     4     visited[v]=true; 
     5     InitQueue(Q);    //辅助队列Q初始化,置空 
     6     EnQueue(Q, v);    //v进队 
     7     while(!QueueEmpty(Q))  //队列非空 
     8     {
     9         DeQueue(Q, u);   //队头元素出队并置为u
    10     for(w=FirstAdjVex(G,u); w>=O; w=NextAdjVex(G,u,w)) 
    11     //依次检查u的所有邻接点w, FirstAdjVex(G,u)表示u的第一个邻接点 
    12     //NextAdjVex(G,u,w)表示u相对于w的下一个临界点,w≧0表示存在邻接点
    13         if(!visited[w])       //w为u的尚未访问的邻接顶点 
    14         {
    15             cout<<w;  
    16             visited[w]=true;  
    17             EnQueue(Q, w);    //w进队
    18         }   //if
    19     }   //while
    20 }

    DFS算法和BFS算法的空间复杂度相同,均为O(n)(借用了堆栈或队列);时间复杂度雨存储结构(邻接矩阵或邻接表)有关,而与搜索路径无关。(邻接矩阵----时间复杂度为O(n^2),邻接表----时间复杂度为O(n+e))

    4、图的应用

    1)最小生成树:

    普里姆算法:时间复杂度为O(n^2),与网中的边数无关,适用于稠密图。

    克鲁斯卡尔算法:时间复杂度为O(eloge),与网中的边数有关,适用于稀疏图。

    2)最短路径

    迪杰斯特拉算法:源点到其余各点,时间复杂度为O(n^2)。

    弗洛伊德算法:每对顶点之间,时间复杂度为O(n^3)。

    二、实践心得

    1、打代码过程中,接触到一个新函数

    //重置visit[]数组
    memset(visit, 0, sizeof(visit));

    2、拯救007中,刚开始看题目没有头绪,后来查询了一番,将图画了出来,便清晰了然,发现这也是应用了图的遍历,可以使用DFS或BFS解决问题。

    3、小测的题目是对图进行遍历,而固定思维总以为是从左至右,从上至下,结果导致出错。日后还是应该具体分析代码。

  • 相关阅读:
    0149-函数可以做参数.abb
    0139-文件操作之二进制方式打开模式(一).abb
    0138-文件操作之基本打开模式.abb
    0130-实例之python实现随机验证码.abb
    0127-python内置函数(一).abb
    0126-lambda表达式.abb
    0113-全局变量和局部变量.abb
    函数的动态参数
    0103-深浅拷贝.abb
    0102-不同数据类型在内存中的存址方式
  • 原文地址:https://www.cnblogs.com/zzssx/p/13124285.html
Copyright © 2011-2022 走看看