16 - 12 - 26 图的存储结构-邻接矩阵、邻接表、十字链表

一、邻接矩阵
<编译通过正常运行>

#include<stdio.h>
#include<stdlib.h>
#define MAXVEX 100  最大顶点数
typedef char VertexType;  //顶点类型
typedef int EdgeType;  //权值类型
#define INFINITY 65535 //用65535来表 ∞
typedef struct 
{
    VertexType vexs [MAXVEX];  //顶点表
    EdgeType arc [MAXVEX][MAXVEX];  //邻接矩阵(边表)
    int numVertexes ,numEdges; //当前的顶点数和边数。
}Graph;  //后面也常写作MGraph。。。。sorry

void CreateGraph ( Graph *G ) 
{
    int i , j , k , w ;
    printf("请输入顶点数和边数(中间加逗号):\n");
    scanf( "%d , %d",&G->numVertexes , &G->numEdges );

    for ( i=0 ; i<G->numVertexes ; i++)
        scanf("%c",&G->vexs[i]);  //读入顶点信息
    for ( i = 0 ; i<G->numVertexes ; i++)
        for ( j = 0 ; j < G->numVertexes ; j++)
            G->arc[i][j] = INFINITY; //邻接矩阵全初始化 
    for ( k = 0 ; k < G->numEdges ; k++ )  //1、
{
printf ( "输入边(vi,vj)上的下标i , j 和 权w:");
            //如果是有向图,就按照方向输入下标
scanf("%d%d%d",&i,&j,&w);
        G->arc[i][j]=w;
G->arc[j][i]=G->arc[i][j] ;
               //无向图是对称矩阵。有向图去掉这句。 
    }
}
// 1、 无向图循环G->numEdges次,有向图要把所有循环条件改成2*G->numEdges次
/*我们总结:创建一个有向图的邻接表需要的元素有很多,
包括:
过称是:输入 : 顶点个数, 边的条数,
       arc[numvertexes][numvertexes]邻接矩阵(边表)
  全部初始化为 INFINITY:∞
  输入邻接矩阵的下标和权值。*/
/*n个顶点e条边的无向网图的构建时间复杂度为O(n+n*n+e),其中邻接矩阵初始化花费O(n*n)的时间*/

void printGraph(Graph g)  //打印“图”
{
    int i, j;
    for(i = 0 ; i < g.numVertexes; i++)
    {
        for(j = 0 ; j < g.numVertexes; j++)   //1、
        {
            printf( " %d  ", g.arc[i][j]);
        }
        printf("\n");
    }
}
int main( ) {
    Graph G;
    CreateGraph(&G);
    printGraph(G); 
    return 0;    
}    

// 1、 无向图循环G->numEdges次,有向图要把所有循环条件改成2*G->numEdges次 。
用邻接矩阵表示有向图时,
若 ai -> aj 的权值 =8
aj -> ai 的权值 =∞
那我们自然可知这条边有方向。

二、邻接表

邻接表的创建       w(゚Д゚)w<正常运行>
#include<stdio.h> 
#include<stdlib.h>
typedef char VertexType;  //顶点类型
typedef int EdgeType;  //权值类型
#define INFINITY 65535 //用65535来表∞
#define MAXVEX 100  最大顶点数


typedef struct node    //边表节点
{
    int adjvex;    //邻接点域
    EdgeType weight;
    struct node *next;  //链域,指向下一个邻接点。
}EdgeNode ;

typedef struct VertexNode   //顶点表节点。
{
    VertexType data;    //顶点域存储定顶点信息。
    EdgeNode *firstedge;  //边表头指针。
}VertexNode , AdjList[ MAXVEX ] ;

typedef struct 
{
    AdjList adjlist;  //
    int numVertexes,numEdges;  //图中当前顶点数和边数
}GraphAdjList;

//无向图的邻接表创建代码
void CreateALGraph(GraphAdjList *G)
{
    int i , j , k ;
    EdgeNode *e;
    printf("输入顶点数和边数\n");
    scanf("%d%d",&G->numVertexes,&G->numEdges);
    for (i = 0; i < G->numVertexes; i++)
    {
        scanf("%d",&G->adjlist[i].data);  //顶点的标号
        G->adjlist[i].firstedge = NULL;
            //将边表置为空表
    }
    for (k = 0; k < G->numEdges; k++)
    {
        printf("输入边(Vi,Vj)上的顶点序号:\n");
        scanf("%d %d",&i,&j);
        e = (EdgeNode *)malloc(sizeof(EdgeNode));
            /*向内存申请空间,生成边表节点*/
        e->adjvex = j;  //邻接序号为j
        e->next = G->adjlist[i].firstedge; 
            /*将e指针指向当前顶点指向的节点*/
        G->adjlist[i].firstedge = e;  
            //将当前结点的指针指向e
        e = (EdgeNode *)malloc(sizeof(EdgeNode));
            /*向内存申请空间,生成边表节点*/
        e->adjvex = i ;  //邻接序号为 i
        e->next = G->adjlist[j].firstedge;
            //将e指针指向当前顶点指向的节点
        G->adjlist[j].firstedge = e;
            /*将当前顶点的指针指向e;*/
    }
}

/*经典头插法,无向图一条边对应两个顶点,所以在循环中,一次就针对i j 分别进行了插入。n个顶点e条边,
所以时间复杂度是O(n+e) */
“再说一遍” 每个顶点Vi的所有邻接点构成一个线性表,用单链表存储,无向图称链表为顶点vi的边表,有向图则称为顶点Vi作为弧尾(头)的出(入)边表。
图中的每一个节点都是表头(顶点)节点,在十字链表中,顶点节点后面连接的是弧节点。/*经典头插法,无向图一条边对应两个顶点,所以在循环中,一次就针对i j 分别进行了插入。n个顶点e条边,
所以时间复杂度是O(n+e) */

一、十字链表

//有向图的十字链表表存储表示-------编译正常运行>
#include<stdio.h>
#include<stdlib.h>
#define MAX_VERTEXT_NUM 20
typedef int InfoType;
typedef char VertextType;
typedef struct ArcBox {  //边表节点信息
    int headVex ;               
    int tailVex ;
    struct ArcBox *headLink;
    struct ArcBox *tailLink;
    InfoType *info;
} ArcBox;
typedef struct VexNode {
    VertextType data;
    ArcBox *firstIn;
    ArcBox *firstOut;
} VexNode;
typedef struct {
    VexNode xList[MAX_VERTEXT_NUM];
    int vexNum;
    int arcNum;
} OLGraph;
void CreateGraphic(OLGraph *G) {
    int i,j,k;
    ArcBox *arcBox;
    printf_s("请输入顶点数和弧数:");
    scanf_s("%d,%d",&G->vexNum, &G->arcNum);
//建立顶点表
    printf_s("建立顶点表\n");
    for (i = 0; i < G->vexNum; i++) {
        printf_s("请输入第%d个顶点:", i);
        fflush(stdin);//刷新缓冲区

        G->xList[i].data = getchar();//输入顶点值
        G->xList [i].firstIn = NULL;//初始化指针
        G->xList[i].firstOut = NULL;//初始化指针
    }
//建立弧表
    printf_s("建立弧表\n");
    for (k = 0; k < G->arcNum; k++) {
      printf_s("请输入(headVex,tailVex)的顶点对序号");
      scanf_s("%d,%d", &i, &j);  //输入时注意加逗号
      arcBox = (ArcBox *)malloc(sizeof(ArcBox));
    //对弧结点赋值
        arcBox->headVex = j;
        arcBox->tailVex = i;
        arcBox->headLink = G->xList[j].firstIn;
        arcBox->tailLink = G->xList[i].firstOut;
        arcBox->info = NULL;
   //完成在入弧和出弧链表表头的插入
        G->xList[j].firstIn = arcBox;
        G->xList[i].firstOut = arcBox;
    }
}
void DisplayGraphic(OLGraph *G) {
    int i;
    ArcBox  *arcBox;
printf("共%d个顶点,%d条弧\n",G->vexNum, G->arcNum);
    for (i = 0; i < G->vexNum; i++) {
        printf_s("顶点%c:", G->xList[i].data);

        arcBox = G->xList[i].firstIn;
        printf_s("入度:");
        while (arcBox) {
            printf_s("%c->%c ", G->xList[arcBox->tailVex].data,G->xList[i].data);
            arcBox = arcBox->headLink;
        }
arcBox = G->xList[i].firstOut;
        printf_s("出度:");
        while (arcBox) {
            printf_s("%c->%c ", G->xList[i].data,G->xList[arcBox->headVex].data);
            arcBox = arcBox->tailLink;
        }
        printf_s("\n");
    }
}

int main() {
    OLGraph *Graph;
    Graph = (OLGraph *)malloc(sizeof(OLGraph));
    CreateGraphic(Graph);
    DisplayGraphic(Graph);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值