数据结构【图篇】



文章目录

  • 数据结构【图篇】
  • 前言
  • 为什么突然想学算法了?
  • 为什么选择码蹄集作为刷题软件?
  • 目录
  • 一、图
  • (一)、图的存储
  • (二)、图的基本操作
  • (三)、最短路径问题
  • 二、拓扑排序
  • 三、结语



前言

为什么突然想学算法了?

> 用较为“官方”的语言讲,是因为算法对计算机科学的所有分支都非常重要。 在绝大多数的计算机科学分支领域中,要想完成任何实质性的工作,理解算法的基础知识并掌握与算法密切相关的数据结构知识是必不可少的。
> 但从实际而言,是因为当下竞争压力逐渐增大,无论走哪一条路,都不免需要一些相对丰富的算法知识,是故,便产生了一个寒假巩固速成算法的计划,可能对于像我这种算法竞赛小白而言,几乎很难,但我仍然还是想尝试一下,毕竟,梦想还是要有的,万一实现了呢?~( ̄▽ ̄~)~

数据结构【图篇】_算法


为什么选择码蹄集作为刷题软件?

码蹄集,是在全国高等学校计算机教学与产业实践资源建设专家委员会(TIPCC) 指导下建设的,其依托全国各大名校计算机系和清华大学出版社等单位的强大资源,旨在为计算机学习爱好者提供全面和权威的计算机习题。
.

数据结构【图篇】_算法_02


目录

一、图

(一)、图的存储

.
参考代码

#define MaxVertexNUm 100                    //顶点数目的最大值
//邻接矩阵法存储带权图(网)
#define INFINITY 0x3f3f3f3f                //宏定义常量“无穷”
typedef char VertexType;                    //顶点的数据类型
typedef int EdgeType;                       //带权图中边上权值的数据类型
typedef struct{
    char Vex[MaxVertexNUm];                 //顶点表
    int Edge[MaxVertexNUm][MaxVertexNUm];   //邻接矩阵,边表
    int vexnum,arcnum;                      //图的当前顶点数和边数/弧数
}MGraph;

//邻接表法(顺序+链式存储)
//边/弧
typedef struct ArcNode{
    int adjvex;                             //边/弧指向那个结点
    struct ArcNode *next;                   //指向下一条弧的指针
    //InfoType info                         //边权值
}ArcNode;

//顶点
typedef struct VNode{
    VertexType data;                        //顶点信息
    ArcNode *first;                         //第一条边/弧
}VNode,AdjList[MaxVertexNUm];

//用邻接表存储的图
typedef struct{
    AdjList vertices;
    int vexnum,arcnum;
}ALGraph;

(二)、图的基本操作

/*
 Adjacent(G,x,y):判断图G是否存在边<x, y>或(x, y)。
 Neighbors(G,x):列出图G中与结点x邻接的边。
 lnsertVertex(G,x):在图G中插入顶点x。
 DeleteVertex(G,x):从图G中删除顶点x。
 AddEdge(G,x,y):若无向边(x, y)或有向边<x, y>不存在,则向图G中添加该边。
 RemoveEdge(G,xy):若无向边(x,y)或有向边<x, y>存在,则从图G中删除该边。
 FirstNeighbor(G,x):求图G中顶点x的第一个邻接点,若有则返回顶点号。若x没有邻接点或图中不存在x,则返回-1。
 NextNeighbor(G,x,y):假设图G中顶点y是顶点x的一个邻接点,返回除y之外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1。
 Get_edge_value(G,x,y):获取图G中边(x,y)或<x, y>对应的权值。
 Set_edge_value(G,x,y,v):设置图G中边(x, y)或<x, y>对应的权值为v。
 */

//广度优先遍历
bool visited[MaxVertexNUm];               //访问标记数组,初始都为false;

void BFSTraverse(MGraph G){                //对图G进行广度优先遍历
    for(i=0;i<G.vexnum;++i)
        visited[i]=FALSE;                 //访问标记数组初始化
    InitQueue(Q);                         //初始化辅助队列Q
    for(i=0;i<G.vexnum;++i)               //从0号顶点开始遍历
        if(!visited[i])                   //对每个连通分量调用一次BFS
            BFS(G,i);                     //vi未访问过,从vi开始BFS
}

void BFS(MGraph G,int v){                 //从顶点v出发,广度优先遍历图G
    visit(v);                             //访问初始顶点v
    visited[v]=TRUE;                      //对w做已访问标记
    Enqueue(Q,v);                         //顶点v入队列Q
    while(!isEmpty(Q)){
        DeQueue(Q,v);                      //顶点v出列
        for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w))
            //检测v所有邻接点
            if(!visited[w]){                //w为v的尚未访问的邻接顶点
                visit(w);                   //访问顶点w
                visited[w]=TRUE;            //对w做已访问标记
                EnQueue(Q,w);                 //顶点w入队列
            }
    }
}

//深度优先遍历
bool visited[MaxVertexNUm];               //访问标记数组,初始都为false;

void DFSTraverse(MGraph G){                //对图G进行深度优先遍历
    for(i=0;i<G.vexnum;++i)
        visited[i]=FALSE;                 //访问标记数组初始化
    InitQueue(Q);                         //初始化辅助队列Q
    for(i=0;i<G.vexnum;++i)               //从0号顶点开始遍历
        if(!visited[i])                   //对每个连通分量调用一次BFS
            DFS(G,i);                     //vi未访问过,从vi开始DFS
}

void DFS(MGraph G,int v){                 //从顶点v出发,深度优先遍历图G
    visit(v);                             //访问初始顶点v
    visited[v]=TRUE;                      //对w做已访问标记
    for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w))
        //检测v所有邻接点
        if(!visited[w]){                //w为v的尚未访问的邻接顶点
           DFS(G,W);
        }
}

(三)、最短路径问题

//最短路径问题
//求顶点u到其他顶点的最短路径——BFS算法
void BFS_MIN_Distance(MGraph G,int u){                 
    //d[i]表示从u到i结点的最短路径
    for(i=0;i<G.vexnum;++i){
        d[i]=INFINITY;                     //初始化路径长度
        path[i]=-1;                        //最短路径从那个顶点过来
    }
    d[u]=0;
    visited[u]=TRUE;
    EnQueue(Q,u);
    while(!isEmpty(Q)){                    //BFS算法主过程
        DeQueue(Q,u);                      //队头元素u出列
        for(w=FirstNeighbor(G,u);w>=0;w=NextNeighbor(G,u,w))
            if(!visited[w]){                //w为v的尚未访问的邻接顶点
                d[w]=d[u]+1;                //路径长度加1
                path[w]=u;                  //最短路径应从u到w
                visited[w]=TRUE;            //对w做已访问标记
                EnQueue(Q,w);               //顶点w入队列
            }
    }
}

二、拓扑排序

//拓扑排序
bool TopologicalSort(MGraph G){
    InitStack(S);                           //初始化栈,存储入度为0的顶点
    for(int i=0;i<G.vexnum;i++)
        if(indegree[i]==0)
            Push(S,i);                      //将所有入度为0的顶点进栈
    int count = 0;                          //计数,记录当前已经输出的顶点数
    while(!IsEmpty(S)){                     //栈不空,则存在入度为0的顶点
        Pop(S,i);                           //栈顶元素出栈
        print[count++]=i;                   //输出顶点i
        for(p=G.vertices[i].firstarc;p;p=p->nextarc){
            //将所有i指向的顶点的入度减1,并且将入度减为0的顶点压入栈S
            v=p->adjvex;
            if(!(--indegree[v]))
                Push(S,v);                  //入度为0,则入栈
        }
    }
    if(count<G.vexnum)
        return false;                       //排序失败,有向图中有回路
    else
        return true;                        //拓扑排序成功
}

//逆拓扑排序
void DFSTraverse(MGraph G){                //对图G进行深度优先遍历
    for(v=0;v<G.vexnum;++v)
        visited[v]=FALSE;                 //访问标记数组初始化
    for(v=0;v<G.vexnum;++v)               //从0号顶点开始遍历
        if(!visited[v])                   //对每个连通分量调用一次BFS
            DFS(G,v);                     //vi未访问过,从vi开始BFS
}

void DFS(MGraph G,int v){                 //从顶点v出发,深度优先遍历图G
    visited[v]=TRUE;                      //对w做已访问标记
    for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w))
        if(!visited[w]){                //w为v的尚未访问的邻接顶点
            DFS(G,W);
        }
    print(v);                           //输出顶点
}

三、结语

感谢大家一直以来的不断支持与鼓励,码题集题库中的进阶塔350题正在逐步更新,之后会逐步跟进星耀,王者的题,尽请期待!!!
同时,也希望这些题能帮助到大家,一起进步,祝愿每一个算法道路上的“苦行僧”们,都能够历经磨难,终成正果,既然选择了这条路,走到了这里,中途放弃,岂不是太过可惜?

另附中国计算机学会的杰出会员、常务理事轩哥博士的B站视频讲解链接https://space.bilibili.com/518554541/?spm_id_from=333.999.0.0,供大家更好的进行学习与刷题~( ̄▽ ̄~)~

愿你的结局,配得上你一路的颠沛流离。

数据结构【图篇】_算法_03