图的代数表示与相互转化

实验一、图的代数表示

 

一、实验内容及要求

编写用于表示有向图的数据结构,以及不同表示方法之间相互转换的程序。

从文件读入一个有向图(带权,n个结点,m条边)的权矩阵表示,输出这个图的关联矩阵、边列表、正向表、邻接表表示。

 

二、设计思路

【数据结构】

二维数组A:保存文件输入,即图的权矩阵

二维数组B:关联矩阵

3个数组Ae, Be, Ze:边列表

3个数组Ap, Bp, Zp:正向表

链表向量adjacent:邻接表

 

【算法】

根据图的各种代数表示的定义直接计算。

 

三、程序编译环境的说明

Windows 10环境Code::Blocks17.12 IDE下开发调试,

清橙OJ(http://www.tsinsen.com/)MinGW g++ 2.7.4下测试通过。

 

四、关键代码分析

1. 文件读写

#include<fstream>
ifstream fin("input.txt");
ofstream fout("output.txt");
fin >> …;
fout << …;
fin.close();
fout.close();

 

2. 初始化

2.1 二维动态数组初始化及其内存释放(不推荐使用,推荐用vector类模板

int **B = new int*[N]();                        
for (i=0; i<N; i++)
{
    B[i] = new int[M]();
}
for (i=0; i<N; i++)
{
    delete []B[i];
}
delete []B;

 

2.2 链表向量的声明、使用与遍历(类模板的嵌套

vector< list<int> > adjacent(N);                          // 创建N个链表组成的向量
adjacent[i].push_back(A[i][j]);
adjacent[i].push_back(j+1);
for (vector< list<int> >::iterator iter_0 = adjacent.begin(); iter_0 != adjacent.end(); iter_0++)
{
	for (list<int>::iterator iter_1 = (*iter_0).begin(); iter_1 != (*iter_0).end(); iter_1++)
	{
		fout << *iter_1 <<" ";
	}
	fout << endl;
}

 

3. 核心算法

       从左到右、从上到下扫描邻接矩阵的每一个元素,若该元素非0,则:

(1)将1和-1填入关联矩阵的下一列;

(2)在边列表A、B、Z数组中分别填入边的起始点、终止点和权值;

(3)在正向表B、Z数组中分别填入边的终止点和权值;

(4)在邻接表中该行对应的链表后增加一个结点。

       开始扫描一行之前,将当前累计边数加1填入正向表A数组的对应位置。


五、实验结果与分析 

1. 一般情形样例

输入:

3

0 5 2

1 0 0

4 0 0

输出:

1 1 -1 -1

-1 0 1 0

0 -1 0 1

1 1 2 3

2 3 1 1

5 2 1 4

1 3 4 5

2 3 1 1

5 2 1 4

5 2 2 3

1 1

4 1

 

2. 边界情形样例

输入:

1

0

输出:

 

 

 \n

 \n

 \n

 \n

1 1

 \n

 \n

 \n

 
六、完整代码
#include<stdio.h>
#include<vector>
#include<list>
using namespace std;

int main()
{
    int N, i=0, j=0, aij, M=0;                          // M: edge counter, N: # of nodes
    scanf_s("%d", &N);
    int **A = new int*[N];                              // A: input adjacent matrix
    for (i=0; i<N; i++)
    {
        A[i] = new int[N];
    }
    // compute # of edges
    for (i=0; i<N; i++)
    {
        for (j=0; j<N; j++)
        {
            scanf_s("%d", &aij);
            A[i][j] = aij;
            if(aij!=0)
            {
                M++;
            }
        }
    }
    // initialize
    int *Ae = new int[M]();
	int *Be = new int[M]();
	int *Ze = new int[M]();                         // 边列表
    int *Ap = new int[N+1]();                                 // 正向表
    int *Bp = new int[M](); 
	int *Zp = new int[M]();                              // 正向表
    int **B = new int*[N]();                                  // 关联矩阵
    for (i=0; i<N; i++)
    {
        B[i] = new int[M]();
    }
    vector< list<int> > adjacent(N);                          // 邻接表
    // compute parameters
    int cnt=0;
    Ap[0] = 1;
    Ap[N] = M+1;
    for (i=0; i<N; i++)
    {
        Ap[i] = cnt+1;
        for (j=0; j<N; j++)
        {
            if(A[i][j]!=0)
            {
                B[i][cnt] = 1;
                B[j][cnt] = -1;
                Ae[cnt] = i+1;
                Be[cnt] = j+1;
                Ze[cnt] = A[i][j];
                Bp[cnt] = j+1;
                Zp[cnt] = A[i][j];
                adjacent[i].push_back(A[i][j]);
                adjacent[i].push_back(j+1);
                cnt++;
            }
        }
    }
    // output
    // 关联矩阵
    for (i=0; i<N; i++)
    {
        for (j=0; j<M; j++)
        {
            printf("%d ", B[i][j]);
        }
        printf("\n");
    }

    // 边列表
    for (i=0; i<M; i++)
    {
        printf("%d ", Ae[i]);
    }
    printf("\n");
    for (i=0; i<M; i++)
    {
        printf("%d ", Be[i]);
    }
    printf("\n");
    for (i=0; i<M; i++)
    {
        printf("%d ", Ze[i]);
    }
    printf("\n");

    // 正向表
    for (i=0; i<N+1; i++)
    {
        printf("%d ", Ap[i]);
    }
    printf("\n");
    for (i=0; i<M; i++)
    {
        printf("%d ", Bp[i]);
    }
    printf("\n");
    for (i=0; i<M; i++)
    {
        printf("%d ", Zp[i]);
    }
    printf("\n");

    // 邻接表
    for (vector< list<int> >::iterator iter_0 = adjacent.begin(); iter_0 != adjacent.end(); iter_0++)
    {
        for (list<int>::iterator iter_1 = (*iter_0).begin(); iter_1 != (*iter_0).end(); iter_1++)
        {
            printf("%d ", *iter_1);
        }
        printf("\n");
    }
    // free memory
    delete []Ae;
    delete []Be;
    delete []Ze;
    delete []Ap;
    delete []Bp;
    delete []Zp;
    for (i=0; i<N; i++)
    {
        delete []B[i];
    }
    delete []B;
    return 0;
}

 


版权声明:本文为da_kao_la原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。