数据结构——图整理代码(邻接表存储图)

数据结构图相关代码整理记录——邻接表存储图

环境CodeBlocks17 运行通过

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <queue>
using namespace std;

#define MAX_VERTEX_NUM 20
typedef char VertexType;    // 顶点数据类型
typedef char InfoArc;   // 弧节点相关信息
typedef enum {DG,DN,UDG,UDN} GraphKind;//图类型{有向图,有向网,无向图,无向网}   (边带权值的图叫网)
typedef struct ArcNode  // 弧节点
{
    int adjvex; // 该弧所指向的顶点在数组中的位置
    int value;  // 弧的权值
    struct ArcNode *nextarcs;   // 指向下一条弧的指针
    InfoArc *info;  // 该弧相关信息的指针
}ArcNode;
typedef struct VNode    // 顶点
{
    VertexType data;    // 顶点信息
    ArcNode *firstarc;  // 指向第一条依附于该顶点的弧的指针
}VNode, AdjList[MAX_VERTEX_NUM];
typedef struct  // 图结构
{
    AdjList vertices;    // 指向订点链表的指针
    int vexnum, arcnum; // 图的当前顶点和弧数
    GraphKind kind;   // 图的种类标志DG,DN,UDG,UDN
}ALGraph;

int visited[MAX_VERTEX_NUM];    // 访问记录数组
int indegree[MAX_VERTEX_NUM];   // 入度记录数组

void CreatGraph_DN(ALGraph &G)
{// 创建有向图
    ArcNode *p,*q;
    int i,j,flag1,flag2,value;  // value 接收输入的权值
    VNode v1,v2;
    G.kind = DN;    // 规定为有向图

    // 输入该有向网的顶点数目和弧的数目
    scanf("%d%d",&G.vexnum,&G.arcnum);getchar();
    // 初始化顶点
    for(i=0;i<G.vexnum;i++)
    {
        scanf("%c ",&G.vertices[i].data);
        G.vertices[i].firstarc = NULL;
    }
    // 请初始化顶点之间的关系 G.arcnum 条弧
    for(i=0;i<G.arcnum;i++)
    {
        flag1=flag2=-1; // 标记
        scanf("%c %c",&v1.data,&v2.data);getchar();
        for(j=0;j<G.vexnum;j++)
        {
            if(G.vertices[j].data == v1.data)
                flag1 = j;
            if(G.vertices[j].data == v2.data)
                flag2 = j;
        }

        if(flag1==-1||flag2==-1)    // 错误输入
        {printf("Input error!\n");exit(-1);}

        else    // 在相关顶点的邻接表头插入新弧节点
        {
            p = (ArcNode *)malloc(sizeof(ArcNode));
            p->nextarcs = NULL;
            p->adjvex = flag2;
            //  没有权值 p->value==?
            q = G.vertices[flag1].firstarc;
            if(q == NULL)   // 弧链表为空
                G.vertices[flag1].firstarc = p;
            else    // 弧链表不为空,接到表尾
            {
                /*
                while(q->nextarcs!=NULL)
                    q = q->nextarcs;
                q->nextarcs = p;
                */
                //方法二插到表头后面
                p->nextarcs = G.vertices[flag1].firstarc;
                G.vertices[flag1].firstarc = p;
            }
        }
    }
}

void CreatGraph_UDG(ALGraph &G)
{// 创建邻接表存储的无向图G
    ArcNode *p,*q;
    int i,j,flag1,flag2;
    VNode v1,v2;
    G.kind = UDG;    // 规定为无向图

    // 输入该有向网的顶点数目和弧的数目
    scanf("%d%d",&G.vexnum,&G.arcnum);getchar();
    // 初始化顶点
    for(i=0;i<G.vexnum;i++)
    {
        scanf("%s ",G.vertices[i].data);
        G.vertices[i].firstarc = NULL;
    }
    // 请初始化顶点之间的关系 G.arcnum 条弧
    for(i=0;i<G.arcnum;i++)
    {
        flag1=flag2=-1; // 标记
        scanf("%s %s",v1.data,v2.data);getchar();
        for(j=0;j<G.vexnum;j++)
        {//以下比较字符串可以使用strcmp
            if(G.vertices[j].data[0] == v1.data[0])
                if(G.vertices[j].data[1] == v1.data[1])
                    if(G.vertices[j].data[2] == v1.data[2])
                        flag1 = j;
            if(G.vertices[j].data[0] == v2.data[0])
                if(G.vertices[j].data[1] == v2.data[1])
                    if(G.vertices[j].data[2] == v2.data[2])
                        flag2 = j;
        }

        if(flag1==-1||flag2==-1)    // 错误输入
        {printf("Input error!\n");exit(-1);}

        else    // 在相关顶点的邻接表头插入新弧节点
        {
            p = (ArcNode *)malloc(sizeof(ArcNode));
            p->nextarcs = NULL;
            p->adjvex = flag2;
            //  没有权值 p->value==?
            q = G.vertices[flag1].firstarc;
            if(q == NULL)   // 弧链表为空
                G.vertices[flag1].firstarc = p;
            else    // 弧链表不为空,插入到表中
            {
                // 方法一 插入到表尾
                /*
                while(q->nextarcs!=NULL)
                    q = q->nextarcs;
                q->nextarcs = p;
                */
                //方法二插到表头后面
                p->nextarcs = G.vertices[flag1].firstarc;
                G.vertices[flag1].firstarc = p;
            }
            //------------------------------
            p = (ArcNode *)malloc(sizeof(ArcNode));
            p->nextarcs = NULL;
            p->adjvex = flag1;
            // DN 没有权值 p->value==?
            q = G.vertices[flag2].firstarc;
            if(q == NULL)   // 弧链表为空
                G.vertices[flag2].firstarc = p;
            else    // 弧链表不为空,插入到表中
            {
                // 方法一 插入到表尾
                /*
                while(q->nextarcs!=NULL)
                    q = q->nextarcs;
                q->nextarcs = p;
                */
                //方法二插到表头后面
                p->nextarcs = G.vertices[flag2].firstarc;
                G.vertices[flag2].firstarc = p;
            }
        }
    }
}


void CountVerNum_DN(ALGraph &G, int *D, int *ID, int* OD)
{//计算各结点的度
	//邻接表存储的有向网,当计算顶点的度时,出度为顶点链表中弧表结点的数目
	//入度则需遍历整个邻接表求得相应的顶点的入度,然后与出度相加得到个顶点的度
    int i;
    ArcNode *p;
    for(i=0;i<G.vexnum;i++) // 初始化
    {
        D[i] = ID[i] = OD[i] = 0;
    }
    for(i=0;i<G.vexnum;i++)
    {
        p = G.vertices[i].firstarc;
        if(p==NULL)
            OD[i]=0;
        else
            while(p!=NULL)
                {
                    OD[i]++;
                    ID[p->adjvex]++;
                    p = p->nextarcs;
                }
    }
    for(i=0;i<G.vexnum;i++)
		D[i]=ID[i]+OD[i];
}

void Display_AdjacencyList_DN(ALGraph &G)
{// 输出邻接表 example:0:A 2 1
    ArcNode *p;
    for(int i=0;i<G.vexnum;i++)
    {
        printf("%d:%c",i,G.vertices[i].data);
        p = G.vertices[i].firstarc;
        while(p)
        {
            printf(" %d",p->adjvex);
            p = p->nextarcs;
        }
        printf("\n");
    }
}

//--------------------------------------------------
int FirstAdjVex(ALGraph &G, int v)
{// 返回表示第v个节点的第一个邻接点的数组下标
    if(G.vertices[v].firstarc==NULL)    // 下个节点不存在
        return -1;
    else    // 下个节点存在
        return G.vertices[v].firstarc->adjvex;
}
int NextAdjVex(ALGraph &G, int v, int w)
{// 返回图G中v的邻接链表中边data值为w的下一个节点的数组下表
    ArcNode *p = G.vertices[v].firstarc;
    while(p->adjvex!=w) // 查找v的弧链表上的w的位置
    {
        p = p->nextarcs;
    }
    if(p->nextarcs!=NULL)    // 下个节点存在
        return p->nextarcs->adjvex;
    else    // 下个节点不存在
        return -1;
}
//--------------------------------------------------

void DFS(ALGraph &G, int v)
{// 从第v个顶点开始递归比深度优先遍历图 连通图 G
    cout<<G.vertices[v].data;
    visited[v] = 1;
    for(int w=FirstAdjVex(G,v); w>=0; w=NextAdjVex(G,v,w))
    // FirstAdjVex(G,v)表示第v个节点的第一个邻接点,NextAdjVex(G,v,w)表示v相对与w的下一个节点
    // w>=0表示存在邻接点
        if(!visited[w])
            DFS(G,w);
}

void DFS_No_Connet(ALGraph &G)
{// 对 !-->非连通图<--! G做深度优先遍历
    for(int v=0; v<G.vexnum; v++)
        visited[v] = 0; // 访问标志数组初始化
    for(int v=0; v<G.vexnum; v++)
        if(!visited[v])
            DFS(G,v);   // 对尚未访问的顶点进行访问

}

void DFS_AL(ALGraph &G, int v)
{// 图G为邻接表 从第v个顶点出发深度优先搜索遍历图G
    int w;
    cout<<G.vertices[v].data;
    visited[v] = 1;
    ArcNode *p = G.vertices[v].firstarc;
    while(p!=NULL)    // 边结点非空
    {
         w = p->adjvex;  // 表示w是v的邻接点
        if(!visited[w]) // w未被访问
            DFS_AL(G,w);    // 递归访问
        p = p->nextarcs;
    } //<end while>
}

void BFS_No_Recursive1(ALGraph &G, int v)
{// 从第v个顶点开始 广度优先 非递归 遍历连通图G
    int i;
    for(i=0; i<G.vexnum; i++)   // 初始化
        visited[i] = 0;
    cout<<G.vertices[v].data<<" ";
    visited[v] = 1;
    queue<int> Q;
    Q.push(v);
    while(!Q.empty())
    {
        int u = Q.front();Q.pop();
        for(int w=FirstAdjVex(G,u); w>=0; w=NextAdjVex(G,u,w))
        {// 依次检查u的所有邻接点;FirstAdjVex(G,u)表示u的第一个邻接点
            //NextAdjVex(G,u,w) 表示u相对于w的下一个邻接点,W>=0表示存在邻接点
            if(!visited[w])
            {
                cout<<G.vertices[w].data<<" ";
                visited[w] = 1;
                Q.push(w);
            }
        }
    }
}

void BFS_No_Recursive2(ALGraph G)
{
    int i,u,w;
    queue<int> Q;
    for(i=0; i<G.vexnum; i++)   // 初始化
        visited[i] = 0;

    for(i=0; i<G.vexnum; i++)
    {
        if(!visited[i])
        {
            cout<<G.vertices[i].data<<" ";
            visited[i] = 1;
            Q.push(i);
            while(!Q.empty())
            {
                u = Q.front(); Q.pop();
                for(w=FirstAdjVex(G,u); w>=0; w=NextAdjVex(G,u,w))
                    if(!visited[w])
                {
                    cout<<G.vertices[w].data<<" ";
                    visited[w] = 1;
                    Q.push(w);
                }// <end for>
            }// <end while>
        }// <end if>
    }// <end for>
}

void DFS_No_Recursive(ALGraph &G)
{//邻接表存储图的非递归深度优先遍历
	ArcNode *p;
	stack<int> S;
	cout <<G.vertices[0].data<<" ";//默认从0结点开始遍历
	visited[0] = 1;//此为遍历标志数组,0:未访问,1:已访问
	S.push(0);
	while (!S.empty())
    {
		p = G.vertices[S.top()].firstarc;
		while (p != NULL)
		{
			if(visited[p->adjvex] != 1)
            {
				cout <<G.vertices[p->adjvex].data<<" ";
				visited[p->adjvex] = 1;
				S.push(p->adjvex);
				break;
			}
            else
			{
				p = p->nextarcs;
			}
		}
		if (p == NULL)
		{
			S.pop();
		}
	}
}

int main()
{
    ALGraph G;
    for(int i=0; i<=MAX_VERTEX_NUM; i++)    // 每次遍历之前记得初始化访问记录数组!!!!
        visited[i] = 0;
    int D[MAX_VERTEX_NUM],ID[MAX_VERTEX_NUM],OD[MAX_VERTEX_NUM];
    // 创建
    CreatGraph_DN(G);
    // 统计度
    CountVerNum_DN(G,D,ID,OD);
    for(int i=0;i<6;i++)
        printf("D:%d ID:%d OD:%d\n",D[i],ID[i],OD[i]);
    // 输出邻接表
    Display_AdjacencyList_DN(G);
    // 遍历邻接表



    return 0;
}

/*
第一组测试数据 data为char
测试数据:
连通图
6 6
A B C D E F
A B
A C
B D
C D
D E
C F

非连通图
6 5
A B C D E F
A B
A C
B D
C D
D E

第二组测试数据 data为char [3]
请修改CreatGraph函数 和 typedef struct VNode
输入:
12 16
c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12
c1 c4
c1 c2
c1 c3
c1 c12
c4 c5
c2 c3
c3 c5
c3 c7
c5 c7
c3 c8
c9 c12
c9 c10
c10 c12
c9 c11
c11 c6
c6 c8
*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值