图的一些简单算法实现

1、类型声明

邻接矩阵

#define MAXV<最大顶点个数>
#define INF 32767   //定义∞
typedef struct
{
    int no;   //顶点编号
    InfoType info;   //顶点其他信息
}VertexType;   //顶点类型
typedef struct
{
    int edges[MAXV][MAXV];   //邻接矩阵数组
    int n,e;   //顶点数,边数
    VertexType vexs[MAXV];   //存放顶点信息
}MatGraph;   //邻接矩阵类型

邻接表

typedef struct ANode
{
    int adjvex;   //该边的邻接点编号
    struct ANode *nextarc;   //指向下一条边的指针
    int weight;   //权值
}ArcNode;
typedef struct Vnode
{
    InfoType info;   //顶点其他信息
    ArcNode *firstarc;   //指向第一个边结点
}VNode;   //邻接表的头结点类型
typedef struct
{
    VNode adjlist[MAXV];   //邻接表的头结点数组
    int n,e;   //顶点数和边数
}AdjGraph;   //邻接表类型

2、不带权有向图邻接矩阵

void InDs1(MatGraph g) //求每个顶点的入度
{
    int i,j,n;
    printf("各顶点入度:\n");
    for(j=0;j<g.n;j++)
    {
        n=0;
        for(i=0;i<g.n;i++)
        {
            if(g.edges[i][j]!=0)
            {
                n++; //累计入度数
            }
        }
        printf("顶点%d:%d\n",j,n);
    }
}

void OutDs1(MatGraph g) //求每个顶点的出度
{
    int i,j,n;
    printf("各顶点出度:\n");
    for(i=0;i<g.n;i++)
    {
        n=0;
        for(j=0;j<g.n;j++)
        {
            if(g.edges[i][j]!=0)
            {
                n++; //累计出度数
            }
        }
    	printf("顶点%d:%d\n",i,n);
    }
}

void ZeroOutDs1(MatGraph g) //求出度为0的顶点
{
    int i,j,n;
    printf("出度为0的顶点:\n");
    for(i=0;i<g.n;i++)
    {
        n=0;
        for(j=0;j<g.n;j++)
        {
            if(g.edges[i][j]!=0)
            {
                n++;
            }
            if(n==0)
            {
                printf("2d\n",i);
            }
        }
    }
    printf("\n");
}

3、不带权有向图邻接表

void InDs2(AdjGraph *G) //求每个顶点的入度
{
    ArcNode *p;
    int A[MAXV],i; //A存放各顶点的入度
    for(i=0;i<G->n;i++) //A中元素初始值0
    {
        A[i]=0;
        
    }
    for(i=0;i<G->n;i++) //扫描所有头结点
    {
        p=G->adjlist[i].firstarc;
        while(p!=NULL) //扫描边结点
        {
            A[p->adjvex]++; //表示i到p->adjvex顶点有一条边
            p=p->nextarc;
        }
    }
    printf("各顶点的入度:\n");
    for(i=0;i<G->n;i++)
    {
        printf("顶点%d:%d\n",i,A[i]);
    }
}

void OutDs2(AdjGraph *G) //求每个顶点的出度
{
    int i,n;
    ArcNode *p;
    printf("各顶点出度为:\n");
    for(i=0;i<G->n;i++) //扫描所有头结点
    {
        n=0;
        p=G->adjlist[i].firstarc;
        while(p!=NULL) //扫描边结点
        {
            n++;
            p=p->nextarc;
        }
        printf("顶点%d:%d\n",i,n);
    }
}

void ZeroOutDs2(AdjGraph *G) //出度为0的顶点数
{
    int i,n;
    ArcNode *p;
    printf("出度为0的顶点数:\n");
    for(i=0;i<G->n;i++) //扫描所有头结点
    {
        n=0;
        p=G->adjlist[i].firtarc;
        while(p!=NULL) //扫描边结点
        {
            n++;
            p=p->nextarc;
        }
        if(n==0) //输出出边为0的顶点编号
        {
            printf("%2d",i);
        }
    }
    printf("\n");
}

4、判断是否存在经过顶点v的回路

int visited[MAXV]; //全局变量数组
void Cycle(AdjGraph *G,int u,int v,int d,bool &has)
{
    //调用初始值has置为false,d为-1
    ArcNode *p;
    int w;
    visited[u]=1; //置已访问的标记
    d++;
    p=G->adjlist[u].firstarc; //p指向顶点u的第一个邻接点
    while(p!=NULL)
    {
        w=p->adjvex;
        if(visited[w]==0) //若顶点w未访问,则递归访问
        {
            Cycle(G,w,v,d,has); //从顶点w出发搜索
        }
        else if(w==v&&d>1) //u到v存在一条边且回路长度大于1
        {
            has=true;
            return;
        }
        p=p->nexterc; //找下个邻接点
    }
}
bool hasCycle(AdjGraph *G,int v) //判断连通图中是否有经过顶点v的回路
{
    bool has=false;
    Cycle(G,v,v,-1,has); //从顶点v出发
    return has;
}

5、判断无向图是否为一棵树

void DFS(AdjGraph *G,int v,int &vn,int &en)
{
    //深度优先遍历图G,并求出遍历过的顶点数vn和边数en
    ArcNode *p;
    visited[v]=1;
    vn++; //遍历过的顶点数增1
    p=G->adjlist[v].firstarc;
    while(p!=NULL)
    {
        en++; //遍历过的边数增1
        if(visited[p->adjvex]==0)
        {
            DFS(G,p->adjvex,vn,en);
        }
        p=p->nextarc;
    }
}
bool isTree(AdjGraph *G) //判断无向图G是否为树
{
    int vn=0,en=0,i;
    for(i=0;i<G->n;i++)
    {
        visited[i]=0;
    }
    DFS(G,1,vn,en);
    //遍历顶点为 G->n 个,遍历边数为 2(G->n-1),则为树
    if(vn==G->n&&en==2*(G->n-1))
    {
        return true;
    }
    else
    {
         return false;   
    }
}

6、源点到其余各点的最短路径

void shortPath(AdjGraph *G,int i)
{
    int qu[MAXV],level[MAXV];
    int fornt=0,raer=0,k,lev; //lev保存i到访问顶点的层数
    ArcNode *p;
    visited[i]=1; //i已经访问,进队
    rear++;
    qu[rear]=i;
    level[rear]=0;
    while(front!=rear) //队非空
    {
        front=(front+1)%MAXV;
        //出队
        k=qu[front];
        lev=level[front];
        if(k!=i)
        {
            printf(" 顶点%d到顶点%d的最短距离是:%d\n",i,k,lev);
        }
        p=G->adjlist[k].firstarc; //取k的边表头指针
        while(p!=NULL) //依次搜索邻接点
        {
            if(visited[p->adjvex==0]) //未被访问过
            {
                visited[p->adjvex]=1;
                rear=(rear+1)%MAXV;
                qu[rear]=p->adjvex; //访问过的邻接点进队
                level[rear]=lev+1;
            }
            p=p->nextarc; //顶点i的下一个邻接点
        }
    }
}

7、所有路径及其长度

int visited[MAXV];
void findPath(AdjGraph *G,int u,int v,int path[],int d,int length)
{
    //d表示 path 中顶点个数,初始为 0;length 表示路径长度,初始为 0
	int w,i;
    ArcNode *p;
    //顶点u加到路径中,d增1
    path[d]=u;
    d++;
    visited[u]=1; //置已访问标记
    if(u==v&&d>0) //找到一条路径就输出
    {
        printf(" 路径长度:%d,路径:",length);
        for(i=0;i<d;i++)
        {
            printf("%2d",path[i]);
        }
		printf("\n");
    }
    p=G->adjlist[u].firstarc; //p指向顶点u的第一个邻接点
    while(p!=NULL)
    {
        w=p->adjvex; //w为顶点u的邻接点
        if(visited[w]==0) //w未访问,递归访问
        {
            findPath(G,w,v,path,d,p->weigth+length);
        }
        p=p->nextarc; //p指向顶点u的下一个邻接点
    }
    visited[u]=0; //重置
}
posted @ 2020-07-20 12:09  我在吃大西瓜呢  阅读(458)  评论(0编辑  收藏  举报