C言語--隣接行列を隣接リストにして操作を行う

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
テンペ
記事: 4
登録日時: 8年前

C言語--隣接行列を隣接リストにして操作を行う

#1

投稿記事 by テンペ » 8年前

C言語についての質問です。
下記のプログラムでは初めにadj_matという隣接行列を定義した後にそれを隣接リストの形に変えています。
adj_index[N_VERT]=index; 以下では、配列adj_listおよびadj_indexを用いて、originから頂点i(i=0~7)までの距離をoriginからの幅優先探索で求め
dist_vecに格納するように、プログラムを作りたいです。G~Mに入るプログラムを教えてください。
現在C言語は猫でもわかるC言語を終えたレベルで、アルゴリズムは一通り学びました。
ちなみにこれはある大学院の過去問になってます、答えがわからないためこちらで質問させていただきました。よろしくお願いします



コード:

#include<stdio.h>
#define UNREACH -1
#define N_VERT 8

const int adj_mat[N_VERT][N_VERT]={
{0,1,0,1,0,1,0,0},
{0,0,1,0,0,0,0,0},
{0,0,0,1,0,0,0,0},
{0,0,0,0,1,0,0,0},
{0,0,0,0,0,1,0,1},
{0,0,0,0,0,0,1,0},
{0,0,1,0,0,0,0,1},
{1,0,0,0,0,0,0,0},
}

void calc_dists(const int origin, int dist_vec[]){
int adj_list[N_VERT * N_VERT],adj_index[N_VERT+1];
int array1[N_VERT],array2[N_VERT];
int* curr=array1, * next=array2, *tmp;
int i,j,index=0,dist=1,len_curr=1,len_next=0;


//隣接行列を隣接リストにする//
for(i=0;i<N_VERT;i++){
adj_index[i]=index;
for(j=0;j<N_VERT;j++){
if(adj_mat[i][j]==1){
adj_list[index++]=j;
}
}
}

//ここ以降何をしているかわからない//
adj_index[N_VERT]=index; 

for(i=0;i<N_VERT;i++){
dist_vec[i]=UNREACH;
}

curr[0]=origin;
dist_vec[origin]=0;
while(len_curr>0){
for(i=0;i<len_curr;i++){
for(j=//G//;j<//H//;j++){
if(//I//==//J//){
//K//=dist;
//L//=//M//;
len_next++;
}
} 
}
tmp=next;
next=curr;
curr=tmp;
len_cur=len_next;
len_next=0;
dist++;
}
}

かずま

Re: C言語--隣接行列を隣接リストにして操作を行う

#2

投稿記事 by かずま » 8年前

インデントを付けてください。

こんなもんかな?

コード:

#include <stdio.h>

#define UNREACH -1
#define N_VERT 8

const int adj_mat[N_VERT][N_VERT] = {
    { 0, 1, 0, 1, 0, 1, 0, 0 },
    { 0, 0, 1, 0, 0, 0, 0, 0 },
    { 0, 0, 0, 1, 0, 0, 0, 0 },
    { 0, 0, 0, 0, 1, 0, 0, 0 },
    { 0, 0, 0, 0, 0, 1, 0, 1 },
    { 0, 0, 0, 0, 0, 0, 1, 0 },
    { 0, 0, 1, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 0, 0, 0, 0, 0 },
};

void calc_dists(const int origin, int dist_vec[])
{
    int adj_list[N_VERT * N_VERT], adj_index[N_VERT + 1];
    int array1[N_VERT], array2[N_VERT];
    int *curr = array1, *next = array2, *tmp;
    int i, j, index = 0, dist = 1, len_curr = 1, len_next = 0;


//隣接行列を隣接リストにする//
    for (i = 0; i < N_VERT; i++) {
        adj_index[i] = index;
        for (j = 0; j < N_VERT; j++) {
            if (adj_mat[i][j] == 1) {
                adj_list[index++] = j;
            }
        }
    }

//ここ以降何をしているかわからない//
    adj_index[N_VERT] = index;
    for (i = 0; i < N_VERT; i++) {
        dist_vec[i] = UNREACH;
    }
    curr[0] = origin;
    dist_vec[origin] = 0;
    while (len_curr > 0) {
        for (i = 0; i < len_curr; i++) {
            for (j = adj_index[curr[i]]; j < adj_index[curr[i]+1]; j++) {
                if (dist_vec[adj_list[j]] == UNREACH) {
                    dist_vec[adj_list[j]] = dist;
                    next[len_next] = adj_list[j];
                    len_next++;
                }
            }
        }
        tmp = next;
        next = curr;
        curr = tmp;
        len_curr = len_next;
        len_next = 0;
        dist++;
    }
}

int main(void)
{
    int dist_vec[N_VERT];
    calc_dists(3, dist_vec);
    printf("dist_vec:");
    for (int i = 0; i < N_VERT; i++)
        printf(" %d", dist_vec[i]);
    printf("\n");
    return 0;
}

テンペ
記事: 4
登録日時: 8年前

Re: C言語--隣接行列を隣接リストにして操作を行う

#3

投稿記事 by テンペ » 8年前

ありがとうございます!理解しました。定義される文字が多すぎて何をどうすればいいのやらと途方に暮れていました(*_*;
dist_vecに数値が入っていなかったら(UNREACH)だったらそこにdistを入れる(distは次のノードに行くたびに1増える)
配列nextにはjから向かうことが出来るノードの番号が入り、小さいループを抜けた後にその中身をcurrに入れる。
そして新しいループに入ればcurr[0]curr[1]←これらは前回のノードからさされたノードから再び新しいところへ向かうノードにdistを入れる。
といった感じでそれぞれの役割があることがわかりました。
とてもすっきりしました。ありがとうございました。

返信

“C言語何でも質問掲示板” へ戻る