C語言利用圖的鄰接表的儲存方式實現求有向圖的入度和出度以及無向圖的度數
阿新 • • 發佈:2018-12-12
Description
圖採用鄰接表為儲存結構,圖中的頂點數為n(0<n<=20),n個頂點的資訊依次為 0,1,...,n-1。
編寫程式,輸入圖的型別(0:無向圖,1:有向圖)、圖中頂點數、邊數、邊的偶對,建立圖的鄰接表。如果是無向圖,計算並輸出每個頂點的度;如果是有向圖,計算並輸出每個頂點的的入度和出度。
Input
輸入:
圖的型別(0 或1)
頂點數,邊數
頂點偶對 (每行一個偶對,如 vi,vj 表示一條邊或者弧)
Output
輸出:
無向圖則依次輸出每個頂點的度,以空格分隔。
有向圖則依次輸出每個頂點的入度,以空格分隔。
換行依次輸出每個頂點的出度,以空格分隔。
Sample Input
1 4,4 0,1 0,2 2,3 3,0
Sample Output
1 1 1 1 2 0 1 1
根據題目的要求,我們先畫出樣例的圖形如下
程式碼和註釋如下,首先建立結構體
#include <stdio.h> #include <stdlib.h> #define Max_Vertex_Num 100 typedef struct ArcNode{ int adjvex; //此題用不到 struct ArcNode *nextarc;//下一個節點 int weight;//權重-此題用不到 }ArcNode; /*表頭節點*/ typedef struct VNode{ int vertex;//表頭陣列的資料 ArcNode *firstarc;//表頭陣列的表頭節點域 }VNode; typedef VNode Adjlist[Max_Vertex_Num];//VNode構成的表頭節點陣列 /*整個鄰接表*/ typedef struct{ Adjlist adjlist;//每個定點後面的連結串列,記錄關聯點 int vexnum,arcnum;//頂點數和邊數 }ALGraph;
主函式的結構如下,先輸入圖的型別(gType)
int main() { ALGraph G; int gType;//定義型別 0是無向圖,1是有向圖 scanf("%d",&gType); CreateALGraph(&G,gType); if(gType==0) CountOutDegree(&G);//計算出度等同於計算所有度數 else{ CountInDegree(&G);//計算入度 CountOutDegree(&G);//計算出度 } return 0; }
有了主函式的大致結構,應該知道先建立一個圖吧,我們需要兩個函式LocateVex獲取輸入的向量對是在函式的哪一行
然後根據輸入的圖的型別分類建立圖
int LocateVex(ALGraph *G,int u){
int i;
for(i = 0; i<G->vexnum;++i)
{
if(G->adjlist[i].vertex == u)
{
return i;
}
}
return -1;
}
/*建立圖*/
void CreateALGraph(ALGraph *G,int gType)
{
ArcNode *p;
int i,j,k;
int v1,v2;
scanf("%d,%d",&G->vexnum,&G->arcnum); //輸入頂點數和邊數
if(gType==0)
{
for(k=0;k<G->vexnum;k++)
{
G->adjlist[k].vertex = k;
G->adjlist[k].firstarc = NULL;
}
k = 0;
while(k<G->arcnum){
scanf("%d,%d",&v1,&v2);
k++;
i = LocateVex(G,v1);
j = LocateVex(G,v2);
/*給第i的表頭新增資料是j的節點*/
p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex = j;
p->nextarc = G->adjlist[i].firstarc;
G->adjlist[i].firstarc = p;
/*給第j的表頭新增資料是i的節點*/
p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex = i;
p->nextarc = G->adjlist[j].firstarc;
G->adjlist[j].firstarc = p;
}
}else{
for(k=0;k<G->vexnum;k++)
{
G->adjlist[k].vertex = k;
G->adjlist[k].firstarc = NULL;
}
k = 0;
while(k<G->arcnum){
scanf("%d,%d",&v1,&v2);
k++;
i = LocateVex(G,v1);
j = LocateVex(G,v2);
/*給第i的表頭新增資料是j的節點——有向圖,不需要給j新增i資料的節點了*/
p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex = j;
p->nextarc = G->adjlist[i].firstarc;
G->adjlist[i].firstarc = p;
}
}
}
怎麼求出度和入度呢?程式碼如下!
/*計算出度*/
void CountOutDegree(ALGraph *G){
int i,j,k;
int count1 = 0;
ArcNode *p;
//根據無向圖的結構,表體中有幾個節點,就有幾度
for(i=0;i<G->vexnum;i++)
{
int degree = 0;
p = G->adjlist[i].firstarc;
while(p!=NULL)
{
degree++;
p=p->nextarc;
}
/*操蛋的輸出格式!*/
if(i!=G->vexnum-1)
printf("%d ",degree);
else
printf("%d",degree);
}
}
/*計算入度*/
void CountInDegree(ALGraph *G)
{
ArcNode *p;
int i;
int j;
//陣列存放每個頂點的入度數量,賦初始值都為0
int arr[G->vexnum];
for(i=0;i<G->vexnum;i++)
{
arr[i]=0;
}
for(i = 0;i<G->vexnum;i++)
{
p = G->adjlist[i].firstarc;
while(p!=NULL)
{
//根據有向圖的結構
//表頭節點後面連線的表體的資料p->adjvex,出現一次就是作為入度一次
//比如0後面有1,2,那麼頂點1和2肯定都作為後驅一次,就有一個入度
arr[p->adjvex]++;
//指標移動到下一個表體
p=p->nextarc;
}
}
/*操蛋的輸出格式!*/
for(i=0;i<G->vexnum;i++){
if(i!=G->vexnum-1)
printf("%d ",arr[i]);
else
printf("%d",arr[i]);
}
printf("\n");
}
總結:其實這個題目對圖的操作還是很簡單的,主要是理解了圖的鄰接表的表示方法其實就是陣列+連結串列的組成結構,剩下的無非就是對單鏈表的操作而已。