1055: 邻接矩阵到邻接表
题目描述
假设无向图G采用邻接矩阵存储,编写一个算法输出邻接表。
输入
第一行为一个整数n,表示顶点的个数(顶点编号为0到n-1),接下来是为一个n*n大小的整数矩阵,表示图的邻接关系。数字为0表示不邻接,1表示邻接。
输出
输出图G的邻接表。第一行表示顶点0可直接到达的顶点编号。其他行定义相同。
样例输入
5
0 1 0 1 1
1 0 1 1 0
0 1 0 1 1
1 1 1 0 1
1 0 1 1 0
样例输出
134
023
134
0124
023
图:
- 图的两种存储结构
(1)邻接矩阵存储方法(较为简单)
(2)邻接(链)表存储方法
题中例子的存储方法如下图所示
法一、指针法
- 定义结构体:
(1)①存储数据 ②存储下一个结点
(2)存储头结点 - 输入邻接矩阵(利用二维数组存储)
- 邻接矩阵–>邻接表(p话有点多建议直接看代码)
(1)嵌套循环遍历矩阵,若i到j有通路(a[i][j]==1):
①定义一个一类结构p,申请空间后令其数据域等于列序号
a.若邻接表头结点为空,
则令其等于p的数据域
b.若邻接表头结点非空,
先申请一个一类结构体q,
后令其连在头结点,
接着用while循环找到非空结点,
最后将p连在非空结点
(2)否则不做处理 - 输出邻接表
#include<bits/stdc++.h>
using namespace std;
typedef struct node
{
int data;//存储数据
struct node *next;//存储下一个结点
}node;
typedef struct headnode
{
struct node *head;//存储头结点
} headnode;
void input(int n, int a[100][100])//输入邻接矩阵
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cin >> a[i][j];
}
}
}
void change(int n, int a[100][100],headnode b[])//邻接矩阵a转换为邻接表b
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(a[i][j]==1)//Vi到Vj两点之间有通路时
{
node *p;
p=new node();//为p申请空间
p->data=j;
p->next=NULL;
if(b[i].head==NULL)//该序号的头结点为空
{
b[i].head=p;//存在头结点
}
else//序号的头结点非空
{
node *q=b[i].head;//申请一个指针q,令其等于头结点
while(q->next!=NULL) q=q->next;//逐个结点往下找,找到非空结点结束
q->next=p;//将p连在非空结点
}
}
}
}
}
void output(int n, headnode b[])//输出邻接表
{
for(int i=0;i<n;i++)
{
if(b[i].head!=NULL)//非空时
{
node *p = b[i].head;
while(p!=NULL)
{
cout << p->data;
p = p->next;
}
}
cout << endl;
}
}
int main()
{
int n;
cin >> n;
int a[100][100];
input(n,a);
headnode b[n];
for(int i=0;i<n;i++) b[i].head=NULL;
change(n,a,b);
output(n, b);
return 0;
}
法二、奇技淫巧之二维数组法
利用二维数组,for循环逐行判断每一列是否为一,为一则输出列序号,否则不做处理。
#include<bits/stdc++.h>
///using namespace std;
int main()
{
int a[100][100],k, m, n, i, j;
scanf("%d", &n);//cin >> n;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%d", &a[i][j]);//cin >> arr[i][j];
}
}
for(m=0;m<n;m++)
{
for(k=0;k<n;k++)
{
if(a[m][k]==1)
{
printf("%d", k);//cout << k;
}
}
printf("\n");//cout << endl;
}
return 0;
}
}
以上方法仅供参考,欢迎互联网广大朋友们提出指正。