【图】【邻接表】【DFS】求两个顶点间所有路径

语言:C语言

图的存储结构:链表

使用的数据结构:栈

图的遍历算法:DFS(深度优先算法)

我的图是这样滴

思路是这样滴:

因为从一个点到另一个点,每一步肯定是经过紧邻它的点,于是乎就要有一个for循环,从紧邻着它的第一个点开始一直到最后,每访问一个点,先判断该点在不在栈内,不在的话压栈,在的话说明已经访问过,再访问就成环了。然后判断它是不是终点。是终点就进入递归,因为判断是在递归函数的开始部分。综合考虑就是每一个for循环判断在栈内是否存在并且是否为终点。一但访问到终点,就输出栈内的所有顶点,就是从起点到终点的序列。然后将栈顶弹出(也就是终点)。返回上一个递归函数。看看终点前一个顶点还有没有其他的临界点可到终点。当该点的所有邻接结点都被访问过,再把该顶点弹出。

代码是这样滴:

#include<stdio.h>
#define maxn 10

//栈的结构体
typedef struct
{
    int top;
    int num[maxn];
}Stack;

//邻接表的边结点
typedef struct
{
    int data;
    int quan;
    struct Arcnode* next;
}Arcnode;

//邻接表的头结点

typedef struct
{
    int data;
    Arcnode* first;
}Vnode;

//图的结构体

typedef struct
{
    int vexnum,arcnum;
    Vnode Vnode[maxn];
}ALGraph;

//图的创建

int CreateGraph(ALGraph *G)
{
    int i;

//先输入图的点数和边数
    printf("请输入图的点数和边数\n");
    scanf("%d%d",&G->vexnum,&G->arcnum);
    for(i=0;i<G->vexnum;i++)
    {
        printf("请输入第%d个顶点的值\n",i+1);
        scanf("%d",&G->Vnode[i].data);
        G->Vnode[i].first=NULL;
    }

//在输入每条边所对应的两个结点,由于是无向图,所以插入链表时,两个顶点所对应的头结点的位置都要插入,采用头插法
    for(i=0;i<G->arcnum;i++)
    {
        int j,k;
        Arcnode* p,*q;
        printf("请输入第%d条边的两个点\n",i+1);
        scanf("%d%d",&j,&k);
        p = (Arcnode*)malloc(sizeof(Arcnode));
        p->data = k;
        p->next = G->Vnode[j].first;
        G->Vnode[j].first = p;
        q = (Arcnode*)malloc(sizeof(Arcnode));
        q->data = j;
        q->next = G->Vnode[k].first;
        G->Vnode[k].first = q;
    }
}

//输出邻接表结构
void showALGraph(ALGraph *G)
{
    int i;
    Arcnode *t;
    for(i=0;i<G->vexnum;i++)
    {
        t= G->Vnode[i].first;
        printf("%d",G->Vnode[i].data);
        while(t)
        {
            printf("->%d",t->data);
            t=t->next;
        }
        printf("\n");
    }
}

//初始化栈
Stack* init()
{
    Stack *s;
    s = (Stack*)malloc(sizeof(Stack));
    if(s==NULL)
    {
        printf("分配失败\n");
        return 0;
    }
    s->top=-1;
    return s;
}
void push(Stack *s,int v)
{
    if(s->top == maxn -1)
        return;
    s->num[++s->top] = v;
}
int pop(Stack *s)
{
    if(s->top == -1)
        return;
    else
        return s->num[s->top--];
}

//查看顶点是否在栈中
int check(Stack *s,int v)
{
    int i;
    for(i=0;i<=s->top;i++)
    {
        if(v==s->num[i])
            return 1;
    }
    return 0;
}

//输出栈内数据,也就是路径
void show(Stack* s)
{
    int m = s->top;
    int a = 0;
    while(a<=m)
    {
        printf("%d",s->num[a++]);
    }
    printf("\n");
}

//找到该结点紧邻的第一个顶点
int findfirst(ALGraph *G,int i)
{
    Arcnode *p;
    if(G->Vnode[i].first)
    {
        p=G->Vnode[i].first;
        //printf("第一个顶点是%d\n",p->data);
        return p->data;
    }
    else 
    {        
        return -1;
    }
}

//找到该结点紧邻的下一个顶点
int findnext(ALGraph *G,int i,int v)
{
    Arcnode *p,*q;
    if(G->Vnode[v].first)
    {
        p=G->Vnode[v].first;
        while(p->data!=i)
            p=p->next;
        q = p->next;
        if(q)
        {
            //printf("下一个顶点是%d\n",q->data);
            return q->data;
        }
        else
             return -1;
    }
    else 
        return -1;
}

//深度优先算法
void DFS(int B,int E,Stack* s,ALGraph *G){
    int i;
    push(s,B);
    if(E==B){
        show(s);
        pop(s);
        return;
    }
    for(i=findfirst(G,B);i!=-1;i=findnext(G,i,B)){
        //show(s);
        if(check(s,i)&&i!=E)
            continue;
        DFS(i,E,s,G);
    }
    pop(s);
}
int main(){
    ALGraph G;
    Stack *s;
    s = init();
    CreateGraph(&G);
    showALGraph(&G);
    DFS(0,2,s,&G);


}

以下是实验数据
/*
5 7
0
1
2
3
4
0 1
0 3
0 4
1 2
1 3
2 3
3 4
*/

输出的是0到2的所有路径

截图

  • 10
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 可以使用深度优先搜索(DFS)或广度优先搜索(BFS)算法来判断任意两个顶点是否存在路径。 具体实现步骤如下: 1. 初始化一个布尔型数组visited,用于记录每个顶点是否被访问过,初始值为false。 2. 从起始顶点开始,对邻接表中的每个相邻顶点进行遍历,如果该相邻顶点未被访问过,则将其标记为已访问,并递归调用该顶点的相邻顶点,直到找到目标顶点或者所有相邻顶点都被访问过。 3. 如果找到目标顶点,则返回true,否则返回false。 4. 如果使用BFS算法,则需要使用一个队列来存储待访问的顶点,每次从队列中取出一个顶点进行访问,并将其相邻顶点加入队列中,直到找到目标顶点或者队列为空。 需要注意的是,如果中存在环,则需要对已访问过的顶点进行标记,以避免死循环。 ### 回答2: 有向是由一些点和有向边连接这些点所组成的,其中每个点表示一个事物,每条有向边表示关系。 邻接表是一种存储的方式,它是由一个一维数组和各个链表组成的,每个数组元素对应一个顶点,每个链表表示以它的数组下标为起点的一条边。 判断任意两个顶点是否存在路径,可以采用深度优先遍历(DFS)的方法,从一个点开始深度遍历整张来找到与该节点路径相通的其他节点。深度遍历可以通过递归实现,具体步骤如下: 1. 从起始节点开始,将该节点标记为已访问,同时输出该节点的值。 2. 查找该节点的邻居节点,如果邻居节点未被访问过,则递归访问它,并将邻居节点标记为已访问。 3. 重复步骤2,直到所有与该节点路径相通的节点都被遍历完。 如果在执行深度优先遍历时遇到目标节点,则说明这两个节点存在路径;否则,两个节点不存在路径。 具体代码实现如下: ``` bool hasPathDFS(int start, int target, vector<vector<int>>& graph, vector<bool>& visited) { if (start == target) { return true; } visited[start] = true; for (int neighbor : graph[start]) { if (!visited[neighbor]) { if (hasPathDFS(neighbor, target, graph, visited)) { return true; } } } return false; } bool hasPath(int start, int target, vector<vector<int>>& graph) { vector<bool> visited(graph.size(), false); return hasPathDFS(start, target, graph, visited); } ``` 其中,hasPath是主函数,hasPathDFS是深度优先遍历的递归函数。graph表示邻接表,visited用于标记是否访问过节点。如果有路径相连,则返回true,否则返回false。 总之,邻接表存储有向,深度优先遍历可以判断任意两个顶点是否存在路径,通过递归访问与起始节点相连的所有节点来查找目标节点。 ### 回答3: 邻接表是一种常用的存储有向的方式,它把每个顶点的出边放在一个链表中,我们可以使用邻接表存储有向,并设计一个算法判断任意两个顶点是否存在路径。 一种朴素的想法是:从起始顶点开始,一层层地往外扩展,看是否能够到达终止顶点。这种方法可以使用深度优先搜索(DFS)或广度优先搜索(BFS)实现。 以下是使用DFS实现的算法步骤: 1. 初始化visited数组为False,用于记录每个顶点的访问状态。 2. 从起始顶点开始,对邻接表链表的第一个节点依次进行深度遍历,如果当前节点未被访问过(visited为False),则将其visited标记为True。如果在这个过程中找到了终止顶点,算法结束并返回True,否则继续对相邻的节点进行DFS搜索。 3. 如果在整个中都无法到达终止顶点,则返回False。 以下是使用BFS实现的算法步骤: 1. 初始化visited数组为False,用于记录每个顶点的访问状态。 2. 从起始顶点开始,将其加入队列中,并将visited标记为True。 3. 从队列中出队一个元素,遍历它的所有相邻节点,如果该节点未被访问过(visited为False),则将其加入队列,并将visited标记为True。 4. 如果在这个过程中找到了终止顶点,算法结束并返回True,否则继续出队下一个元素。 5. 如果在整个中都无法到达终止顶点,则返回False。 无论是DFS还是BFS,其时复杂度都是O(V+E),其中V表示顶点数,E表示边数。因此,当有多组顶点需要判断时,如果规模比较大,可以考虑预处理出每对顶点的路劲,以便快速查询。此外,对于特定的结构化,比如DAG(有向无环),还可以使用拓扑排序等高效算法,更快地判断两个顶点是否存在路径
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值