ページ 11

ダイクストラ法

Posted: 2014年8月03日(日) 21:45
by びあでゅf
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<malloc.h>
#include<string.h>
#include<limits.h>
#define VERTEX_NUM 100000
struct AVL_Node *AVL_Tree;
struct Vertex{
char name[100];
int d; //出発点からの距離
int is_visited;
struct Edgelist *edge_head;
struct Vertex *shortest_path;
};
struct Edgelist {
int length; //辺の長さ
struct Vertex *to;
struct Edgelist *next;
};


int Max(int lh, int rh){
int Max;
Max = lh;
if(lh <= rh)Max = rh;
return Max;
}

void initialize_vertex(struct Vertex *v, char *name){
strcpy(v->name,name);
v->d=INT_MAX/2; //int型の最大値
v->edge_head=NULL;
v->shortest_path=NULL;
v->is_visited=0;
}
void connect_dir(struct Vertex *from, struct Vertex *to, int length){
struct Edgelist *new_edge;
new_edge=(struct Edgelist *)malloc(sizeof(struct Edgelist));
new_edge->to = to;
new_edge->next= from->edge_head;
from->edge_head=new_edge;
new_edge->length=length;
}
struct AVL_Node{
struct Vertex *v; // 頂点をおぼえる
struct AVL_Node *left;
struct AVL_Node *right;
int h;
};
struct AVL_Node* new_AVL_Node(struct Vertex *v){
struct AVL_Node *n;
n=(struct AVL_Node*)malloc(sizeof(struct AVL_Node));
n->v=v;
n->h=0; n->left=NULL; n->right=NULL;
return n;
}
struct AVL_Node *new_AVL_Node(struct Vertex *v);
struct AVL_Node *insert_v(struct AVL_Node *p, struct Vertex *v);
struct AVL_Node *insert_n(struct AVL_Node *p, struct AVL_Node*x);
struct AVL_Node *rotate(struct AVL_Node *p);
int compare_vertex(struct Vertex *a, struct Vertex *b);
void set_height(struct AVL_Node *p);
struct AVL_Node *find_min(struct AVL_Node *T_root);
struct AVL_Node *remove_min(struct AVL_Node *T_root);
struct AVL_Node *delete_v(struct AVL_Node *T_root, struct Vertex *v);
int compare_vertex(struct Vertex *a, struct Vertex *b){
if(a->d< b->d){
return -1;
} else if( a->d > b->d){
return 1;
} else {
return strcmp(a->name,b->name);
}
}

void set_height(struct AVL_Node *p){
if(p==NULL){
return ;
} else if(p->left==NULL && p->right==NULL){
p->h=0;
} else if(p->left==NULL && p->right!=NULL){
p->h=p->right->h+1;
} else if(p->left!=NULL && p->right==NULL){
p->h=p->left->h+1;
} else {
p->h=Max(p->left->h,p->right->h)+1;
}
}
//*関数maxは自分で作る*//
struct AVL_Node *
insert_n(struct AVL_Node *p, struct AVL_Node *x){
if(x==NULL){ return p; }
if(compare_vertex(x->v,p->v)<0){
if(p->left==NULL){ p->left=x; }
else { p->left = insert_n(p->left, x); }
} else if(compare_vertex(x->v,p->v)>0){
if(p->right==NULL){ p->right=x; }
else { p->right = insert_n(p->right,x); }
} else{
return p;
}
set_height(p);
return rotate(p); /* 回転による根の入替に対応*/
}

struct AVL_Node* insert_v(struct AVL_Node *p, struct Vertex *v){
struct AVL_Node *n= new_AVL_Node(v);
if(p!=NULL){ return insert_n(p,n); }
else { return n; }
}

struct AVL_Node* rotate(struct AVL_Node *p){
int lh=-1, rh=-1, llh=-1,lrh=-1, rlh=-1,rrh=-1;
if(p->left!=NULL){
lh=p->left->h;
if(p->left->left!=NULL){ llh=p->left->left->h;}
if(p->left->right!=NULL){lrh=p->left->right->h;}
}
if(p->right!=NULL){
rh=p->right->h;
if(p->right->left!=NULL){ rlh=p->right->left->h;}
if(p->right->right!=NULL){ rrh=p->right->right->h;}
}
if(lh-rh<=1 && rh-lh<=1){ return p; }
if(lh < rh){ /* 右の子が高い*/
struct AVL_Node *A=p, *B=p->right;
struct AVL_Node *Y=B->left;
if(rlh<rrh){ /*右の右の孫が高い:1重回転*/
B->left=A; A->right=Y;
set_height(A); set_height(B);
return B;
} else {/*右の左の孫が高い:2重回転 */
struct AVL_Node *C=Y, *Y1=C->left, *Y2=C->right;
C->left=A; C->right=B; A->right=Y1; B->left=Y2;
set_height(A); set_height(B); set_height(C);
return C;
}
}else { /*左の子が高い*/
struct AVL_Node *A=p, *B=p->left;
struct AVL_Node *Y=B->right;
if(llh > lrh){/* 左の左の孫が高い:1重回転*/
B->right=A; A->left=Y;
set_height(A); set_height(B);
return B;
} else {/*左の右の孫が高い:2重回転*/
struct AVL_Node *C=Y, *Y1=C->left, *Y2=C->right;
C->left=B; C->right=A; B->right= Y1; A->left=Y2;
set_height(A); set_height(B); set_height(C);
return C;
}
}
}


struct AVL_Node *find_min(struct AVL_Node *p){
struct AVL_Node *q;
if(p==NULL){
return NULL;
}
for(q=p;q->left!=NULL;q=q->left){
; /* なにもしない*/
}
/* qに左の子が存在しないのでqは最小値 */
return q;
}

struct AVL_Node *remove_min(struct AVL_Node *p){
if(p==NULL){
return NULL;
} else if(p->left==NULL) {
return p->right;
} else if(p->left->left==NULL){
/*左の左の孫が無いならば、pは最小値の親*/
p->left=p->left->right;
set_height(p);
return rotate(p);
} else {
p->left=remove_min(p->left);
set_height(p);
return rotate(p);
}
}

struct AVL_Node *delete_v(struct AVL_Node *p, struct Vertex *v){
struct AVL_Node *min_node;
if(p==NULL || v==NULL){
return NULL;
}
if(compare_vertex(v,p->v)<0){
p->left=delete_v(p->left,v);
set_height(p);
return rotate(p);
} else if(compare_vertex(v,p->v)>0){
p->right=delete_v(p->right,v);
set_height(p);
return rotate(p);
}

if(p->right==NULL){
struct AVL_Node *left= p->left;
free(p);
return rotate(left);
} else {
min_node=find_min(p->right);
p->right=remove_min(p->right);
min_node->left=p->left;
min_node->right=p->right;
free(p);
set_height(min_node);
return rotate(min_node);

}}

void read_file(char *filepath,struct Vertex vertex[]){
FILE *fp;
fp=fopen(filepath,"rt");
if(fp==NULL){
printf("ファイルオープン失敗\n%s\n",filepath); return;
}
while(!feof(fp)){
char buf[1000]; int from, to, length;
fgets(buf,1000,fp);
if(buf[0]!='a') continue;
sscanf(buf,"%c %d %d %d",&buf[0], &from, &to, &length);
connect_dir(&vertex[from],&vertex[to],length);
}
fclose(fp);
}

struct Vertex* extract_nearest_AVL();
void add_all_vertices_to_AVL_Tree(struct Vertex *s);
void Dijkstra_fast(struct Vertex *s);


void add_all_vertices_to_AVL_Tree(struct Vertex *s){
struct Edgelist *e;
s->is_visited=1;
AVL_Tree=insert_v(AVL_Tree,s);
for(e=s->edge_head; e!=NULL; e=e->next){
if(e->to->is_visited==0){
add_all_vertices_to_AVL_Tree(e->to);
}
}
return;
}

struct Vertex* extract_nearest_AVL(){
struct AVL_Node *min_node;
struct Vertex *min_vertex;

min_node=find_min(AVL_Tree);
min_vertex=min_node->v;
AVL_Tree=delete_v(AVL_Tree,min_vertex); return min_vertex;
}

void Dijkstra_fast(struct Vertex *s){
struct Edgelist *e; struct Vertex *u;
s->d=0;
add_all_vertices_to_AVL_Tree(s);
while(AVL_Tree!=NULL){
u=extract_nearest_AVL();
for( e= u->edge_head; e!=NULL; e=e->next){
if(e->to->d > u->d + e->length){
AVL_Tree=delete_v(AVL_Tree,e->to);
e->to->d=u->d+e->length;
e->to->shortest_path=u;
AVL_Tree=insert_v(AVL_Tree,e->to);
}
}
}
}

int main(void ){
struct Vertex *p;
char filename[]="C:\\Users\\G\\Desktop\\USA-road-d.NY.gr.txt";
int i,j;
time_t start,end;
struct Vertex *vertex_array=
(struct Vertex *)malloc(sizeof(struct Vertex)*VERTEX_NUM);
printf("初期化中...");
for(i=0;i<VERTEX_NUM;i++){
char name[100];
sprintf(name,"V%d",i);
initialize_vertex(&vertex_array,name);
}
printf("初期化完了\n");
printf("地図読み込み中...");

read_file(filename,vertex_array);
printf("地図読み込み完了\n");

AVL_Tree=NULL;
start=clock();
Dijkstra_fast(&vertex_array[999]);
end=clock();
for(p=&vertex_array[9999];p!=NULL;p=p->shortest_path){
printf("%s<-- ", p->name);
}
printf("最短路の長さは%d\n", vertex_array[9999].d);
printf("%5.4f秒でした\n",(end-start)/(double)CLOCKS_PER_SEC);
getchar(); return 0;


}



Borlandです

exeは動作を停止しましたと出て動きません

どうすれば動きますか

Re: ダイクストラ法

Posted: 2014年8月03日(日) 21:54
by みけCAT
とりあえず、コードを提示するときはBBcodeを有効にした状態でcodeタグで囲み、
かつ適切なインデントをしていただけると、見やすくて助かります。

Re: ダイクストラ法

Posted: 2014年8月03日(日) 22:06
by みけCAT
USA-road-d.NY.grを入力として用いて実行したところ、
41行目の

コード:

new_edge->next= from->edge_head;
でアクセス違反が出たので、
おそらく木の回転にバグがあるのではないかと思います。
fromの値がおかしいかもしれません。

VERTEX_NUMの値を10倍にしたらここでのアクセス違反は出なくなりました。
びあでゅf さんが書きました:どうすれば動きますか
デバッグをしましょう。

Re: ダイクストラ法

Posted: 2014年8月03日(日) 22:25
by みけCAT
まずはVERTEX_NUMの値が入力の頂点数より少なかったため、確保したメモリ領域以外にアクセスしてしまったようです。
次の問題は、 add_all_vertices_to_AVL_Tree関数での再帰が深すぎることのようです。

Re: ダイクストラ法

Posted: 2014年8月03日(日) 22:31
by みけCAT
gcc 4.8.1を用いてスタックサイズ100MBでコンパイルしたところ、次のアクセス違反が出ました。
115行目

コード:

if(p->left!=NULL){
で、pがNULLになっていました。

Re: ダイクストラ法

Posted: 2014年8月03日(日) 22:44
by みけCAT
rotate関数の変数宣言の直後(115行目)に

コード:

	if(p==NULL)return NULL;
という行を入れると、アクセス違反が怒らずに結果が出力されました。
結果が正しいかは検証していません。

実行結果(YUKI.N>はプロンプトを表す)

コード:

YUKI.N>gcc --version
gcc (GCC) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


YUKI.N>gcc -O2 -s -static -o daikusutorahou2_o2 daikusutorahou2.c -Wall -Wextra
-Wl,--stack,10485760
daikusutorahou2.c: In function 'main':
daikusutorahou2.c:278:8: warning: unused variable 'j' [-Wunused-variable]
  int i,j;
        ^

YUKI.N>echo a | daikusutorahou2_o2
初期化中...初期化完了
地図読み込み中...地図読み込み完了
V9999<-- V9998<-- V10000<-- V9993<-- V10003<-- V10002<-- V9997<-- V10009<-- V100
08<-- V10010<-- V10027<-- V10016<-- V10019<-- V7291<-- V7290<-- V7254<-- V7253<-
- V10024<-- V10023<-- V10044<-- V10042<-- V10043<-- V232828<-- V232825<-- V23282
6<-- V232832<-- V232831<-- V232836<-- V232835<-- V232838<-- V232896<-- V232898<-
- V232905<-- V232906<-- V232908<-- V232910<-- V232911<-- V232923<-- V232925<-- V
232860<-- V232893<-- V233549<-- V233554<-- V233550<-- V233553<-- V233557<-- V233
552<-- V233537<-- V233538<-- V233535<-- V233532<-- V233474<-- V233467<-- V233466
<-- V233481<-- V233478<-- V233479<-- V233490<-- V233494<-- V233488<-- V233485<--
 V233486<-- V233471<-- V233468<-- V233470<-- V233483<-- V233463<-- V233461<-- V2
33453<-- V233452<-- V233447<-- V233271<-- V233270<-- V234707<-- V233428<-- V2334
27<-- V233429<-- V233430<-- V239208<-- V240019<-- V240020<-- V240033<-- V263715<
-- V240037<-- V240039<-- V240079<-- V240078<-- V240583<-- V240604<-- V240605<--
V261435<-- V240987<-- V240988<-- V240989<-- V261433<-- V240217<-- V240993<-- V24
1009<-- V241048<-- V241102<-- V241101<-- V241113<-- V241119<-- V244637<-- V24463
5<-- V244636<-- V244638<-- V244639<-- V241456<-- V241455<-- V241461<-- V244640<-
- V261216<-- V244658<-- V244657<-- V244675<-- V244718<-- V244676<-- V244678<-- V
244724<-- V244725<-- V244702<-- V244726<-- V244728<-- V244739<-- V244741<-- V244
744<-- V244746<-- V244748<-- V244878<-- V244880<-- V244884<-- V244888<-- V244900
<-- V244902<-- V244907<-- V244910<-- V244914<-- V256548<-- V256549<-- V261357<--
 V235633<-- V235632<-- V245071<-- V245075<-- V245074<-- V245073<-- V245072<-- V2
45335<-- V245336<-- V245337<-- V245353<-- V245358<-- V245405<-- V245415<-- V2454
17<-- V245422<-- V245519<-- V245520<-- V245524<-- V245530<-- V245533<-- V245534<
-- V245551<-- V245560<-- V245565<-- V245568<-- V245762<-- V247501<-- V247505<--
V247512<-- V247511<-- V247526<-- V247527<-- V247529<-- V247525<-- V247531<-- V24
7570<-- V247574<-- V247576<-- V247579<-- V247573<-- V247710<-- V247711<-- V24771
3<-- V247720<-- V247723<-- V247727<-- V247758<-- V247760<-- V247761<-- V247776<-
- V247777<-- V247778<-- V247779<-- V247782<-- V247901<-- V247916<-- V247910<-- V
247911<-- V257672<-- V257674<-- V257726<-- V258469<-- V258467<-- V258476<-- V258
497<-- V258539<-- V258541<-- V258542<-- V258543<-- V258551<-- V258555<-- V258557
<-- V258558<-- V259883<-- V259884<-- V259914<-- V259918<-- V259919<-- V259920<--
 V259951<-- V259950<-- V259954<-- V260007<-- V260008<-- V260009<-- V260018<-- V2
60022<-- V261196<-- V260074<-- V260075<-- V260076<-- V260081<-- V260083<-- V2600
77<-- V260092<-- V260093<-- V260004<-- V260094<-- V4927<-- V4929<-- V4877<-- V48
83<-- V4882<-- V4460<-- V4459<-- V4895<-- V4898<-- V4900<-- V4902<-- V4903<-- V4
919<-- V4921<-- V4922<-- V4924<-- V4926<-- V5031<-- V5251<-- V5255<-- V5267<-- V
5269<-- V5281<-- V5289<-- V5278<-- V5291<-- V5388<-- V5391<-- V5392<-- V66<-- V5
411<-- V5412<-- V5413<-- V5422<-- V5424<-- V5425<-- V5431<-- V5418<-- V5680<-- V
104<-- V1677<-- V1679<-- V1579<-- V1688<-- V1584<-- V1585<-- V1689<-- V1591<-- V
1739<-- V1740<-- V1741<-- V1742<-- V1631<-- V1632<-- V1813<-- V1814<-- V1634<--
V1815<-- V1817<-- V1825<-- V1828<-- V1671<-- V1837<-- V1674<-- V1675<-- V1673<--
 V1934<-- V1931<-- V1935<-- V1939<-- V1937<-- V1938<-- V1945<-- V1944<-- V1923<-
- V1964<-- V1963<-- V1965<-- V1874<-- V1875<-- V1900<-- V2001<-- V1984<-- V1989<
-- V1992<-- V1993<-- V1997<-- V1996<-- V2000<-- V2022<-- V2019<-- V2027<-- V2029
<-- V2329<-- V2334<-- V2333<-- V2339<-- V2338<-- V2340<-- V2366<-- V2369<-- V991
<-- V990<-- V989<-- V977<-- V969<-- V980<-- V979<-- V988<-- V987<-- V996<-- V995
<-- V994<-- V998<-- V999<-- 最短路の長さは479435
1.4890秒でした

YUKI.N>
※スタックサイズを10MBに変更していますが、仕様です。1MBではアクセス違反が発生しました。