다음은 C언어로 작성한 너비 우선 탐색 알고리즘 소스 코드입니다. 너비 우선 탐색 알고리즘을 우선 순위 큐를 이용하여 작성하였습니다.
//common.h #pragma once //헤더 파일을 한 번만 포함해서 컴파일 #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <string.h> #include <malloc.h> #include <memory.h> #include <time.h> #pragma warning(disable:4996) //4996컴파일 경고 메시지 출력 해제
//Array.h #pragma once typedef void * Element; typedef struct _Array Array; struct _Array { Element *base; int capacity; int usage; }; typedef Element *Iterator; Array *New_Array(); void Delete_Array(Array *arr); void Array_SetSize(Array *arr,int capacity,Element data); void Array_PushBack(Array *arr,Element data); void Array_Insert(Array *arr,Iterator pos,Element data); void Array_SetAt(Array *arr,int index,Element data); Element Array_GetAt(Array *arr,int index); Iterator Array_Begin(Array *arr); Iterator Array_End(Array *arr); void Array_Erase(Array *arr,Iterator pos);
//Array.c #include "Array.h" #include <malloc.h> #include <memory.h> Array *New_Array() { Array *arr = 0; arr = (Array *)malloc(sizeof(Array)); arr->base = 0; arr->capacity = arr->usage = 0; return arr; } void Delete_Array(Array *arr) { if(arr->base) { free(arr->base); } free(arr); } void Array_SetSize(Array *arr,int capacity,Element data) { arr->capacity = capacity; arr->base = (Element *)realloc(arr->base,sizeof(Element)*arr->capacity); for( ;arr->usage<arr->capacity; arr->usage++) { arr->base[arr->usage] = data; } } void Array_PushBack(Array *arr,Element data) { Iterator at = Array_End(arr); Array_Insert(arr,at,data); } void Array_Insert(Array *arr,Iterator pos,Element data) { int index = pos - arr->base; int mcount = arr->usage - index; if(arr->capacity == arr->usage) { if(arr->capacity) { arr->capacity*=2; } else { arr->capacity = 1; } arr->base = (Element *)realloc(arr->base,sizeof(Element)*arr->capacity); } memcpy(arr->base+index+1,arr->base+index,sizeof(Element)*mcount); arr->base[index] = data; arr->usage++; } void Array_SetAt(Array *arr,int index,Element data) { if((index>=0)&&(index<arr->usage)) { arr->base[index] = data; } } Element Array_GetAt(Array *arr,int index) { if((index>=0)&&(index<arr->usage)) { return arr->base[index]; } return 0; } Iterator Array_Begin(Array *arr) { return arr->base; } Iterator Array_End(Array *arr) { return arr->base+arr->usage; } void Array_Erase(Array *arr,Iterator pos) { int index = pos - arr->base; int mcount = arr->usage - index -1; memcpy(pos,pos+1,sizeof(Element)*mcount); arr->usage--; }
//LinkedList.h #pragma once typedef void * Element; typedef struct _Node Node; typedef Node *Link; struct _Node { Link next; Link prev; Element data; }; typedef struct _LinkedList LinkedList; struct _LinkedList { Link head; Link tail; int usage; }; LinkedList *New_LinkedList(); void Delete_LinkedList(LinkedList *linkedlist); void LinkedList_PushBack(LinkedList *linkedlist,Element data); void LinkedList_Insert(LinkedList *linkedlist,Link pos,Element data); Link LinkedList_Begin(LinkedList *linkedlist); Link LinkedList_End(LinkedList *linkedlist); void LinkedList_Erase(LinkedList *linkedlist,Link pos);
//LinkedList.c #include "LinkedList.h" #include <malloc.h> #include <memory.h> Link New_Node(Element data) { Link link = (Link)malloc(sizeof(Node)); link->data = data; link->next = link->prev = 0; return link; } void HangNode(Link link,Link pos) { link->prev = pos->prev; link->next = pos; pos->prev->next = link; pos->prev = link; } void DisconnectNode(Link pos) { pos->prev->next = pos->next; pos->next->prev = pos->prev; } LinkedList *New_LinkedList() { LinkedList *linkedlist = 0; linkedlist = (LinkedList *)malloc(sizeof(LinkedList)); linkedlist->head = New_Node(0); linkedlist->tail = New_Node(0); linkedlist->head->next = linkedlist->tail; linkedlist->tail->prev = linkedlist->head; linkedlist->usage = 0; return linkedlist; } void Delete_LinkedList(LinkedList *linkedlist) { Link seek = linkedlist->head; while( seek != linkedlist->tail) { seek = seek->next; free(seek->prev); } free(linkedlist->tail); free(linkedlist); } void LinkedList_PushBack(LinkedList *linkedlist,Element data) { LinkedList_Insert(linkedlist,linkedlist->tail,data); } void LinkedList_Insert(LinkedList *linkedlist,Link pos,Element data) { Link link = New_Node(data); HangNode(link,pos); linkedlist->usage++; } Link LinkedList_Begin(LinkedList *linkedlist) { return linkedlist->head->next; } Link LinkedList_End(LinkedList *linkedlist) { return linkedlist->tail; } void LinkedList_Erase(LinkedList *linkedlist,Link pos) { DisconnectNode(pos); linkedlist->usage--; }
//PriorityQueue.h #pragma once #include "LinkedList.h" typedef struct _PriorityQueue PriQueue; typedef int (*Compare)(Element el1,Element el2); struct _PriorityQueue { LinkedList *list; Compare compare; }; PriQueue *New_PriorityQueue(Compare compare); void Delete_PriQueue(PriQueue *pq); void PriQueue_Put(PriQueue *pq, Element data); Element PriQueue_Get(PriQueue *pq); int PriQueue_IsEmpty(PriQueue *pq);
//PriorityQueue.c #include "PriorityQueue.h" #include <malloc.h> #include <memory.h> PriQueue *New_PriorityQueue(Compare compare) { PriQueue *pq = (PriQueue *)malloc(sizeof(PriQueue)); pq->list = New_LinkedList(); pq->compare = compare; return pq; } void Delete_PriQueue(PriQueue *pq) { Delete_LinkedList(pq->list); free(pq); } void PriQueue_Put(PriQueue *pq, Element data) { Link seek = LinkedList_Begin(pq->list); Link end = LinkedList_End(pq->list); for( ;seek != end; seek=seek->next) { if(pq->compare(seek->data, data)>0) { break; } } LinkedList_Insert(pq->list,seek,data); } Element PriQueue_Get(PriQueue *pq) { Link begin; if(PriQueue_IsEmpty(pq)) { return 0; } begin = LinkedList_Begin(pq->list); LinkedList_Erase(pq->list,begin); return begin->data; } int PriQueue_IsEmpty(PriQueue *pq) { return pq->list->usage == 0; }
//Graph.h #pragma once #include "Array.h" typedef const char * Vertex; typedef struct _Edge Edge; struct _Edge { Vertex ep1; Vertex ep2; int weight; }; typedef struct _Graph Graph; struct _Graph { Array *vertexs; Array *edges; }; Graph *New_Graph(); void Delete_Graph(Graph *graph); int Graph_AddVertex(Graph *graph,Vertex pt); int Graph_AddEdge(Graph *graph,Vertex ep1, Vertex ep2, int weight); int Graph_ExistVertex(Graph *graph,Vertex pt); int Graph_ExistEdge(Graph *graph,Vertex ep1, Vertex ep2); void Graph_View(Graph *graph); void Graph_ViewVertexs(Graph *graph); void Graph_ViewEdges(Graph *graph); void Graph_FindNeighvor(Graph *graph,Vertex ep, Array *neighvor); int Graph_GetWeight(Graph *graph,Vertex ep1, Vertex ep2);
//Graph.c #include "Graph.h" #include <malloc.h> #include <string.h> #include <stdio.h> Edge *New_Edge(Vertex ep1, Vertex ep2, int weight) { Edge *edge = 0; edge = (Edge *)malloc(sizeof(Edge)); edge->ep1 = ep1; edge->ep2 = ep2; edge->weight = weight; return edge; } Vertex Edge_AnOther(Edge *edge,Vertex pt) { if(strcmp(edge->ep1,pt)==0) { return edge->ep2; } if(strcmp(edge->ep2,pt)==0) { return edge->ep1; } return ""; } int Edge_Include(Edge *edge,Vertex pt) { return (strcmp(edge->ep1,pt)==0)||(strcmp(edge->ep2,pt)==0); } Graph *New_Graph() { Graph *graph = 0; graph = (Graph *)malloc(sizeof(Graph)); graph->vertexs = New_Array(); graph->edges = New_Array(); return graph; } void Delete_Graph(Graph *graph) { Iterator seek = 0, end = 0; Edge *edge = 0; seek = Array_Begin(graph->edges); end = Array_End(graph->edges); for(seek = seek; seek != end; ++seek) { edge = (Edge *)(*seek); free(edge); } Delete_Array(graph->vertexs); Delete_Array(graph->edges); free(graph); } int Graph_AddVertex(Graph *graph,Vertex pt) { if(Graph_ExistVertex(graph,pt)) { return 0; } Array_PushBack(graph->vertexs,(Element)pt); return 1; } int Graph_AddEdge(Graph *graph,Vertex ep1, Vertex ep2, int weight) { if(Graph_ExistVertex(graph,ep1) && Graph_ExistVertex(graph,ep2)) { Edge *edge = 0; if(Graph_ExistEdge(graph,ep1,ep2)) { return 0; } edge = New_Edge(ep1,ep2,weight); Array_PushBack(graph->edges,edge); return 1; } return 0; } int Graph_ExistVertex(Graph *graph,Vertex pt) { Iterator seek = 0, end = 0; Vertex stored_pt = 0; seek = Array_Begin(graph->vertexs); end = Array_End(graph->vertexs); for(seek = seek; seek != end; ++seek) { stored_pt = (Vertex)(*seek); if(strcmp(stored_pt,pt)==0) { return 1; } } return 0; } int Graph_ExistEdge(Graph *graph,Vertex ep1, Vertex ep2) { Iterator seek = 0, end = 0; Edge *stored_eg = 0; seek = Array_Begin(graph->edges); end = Array_End(graph->edges); for(seek = seek; seek != end; ++seek) { stored_eg = (Edge *)(*seek); if(Edge_Include(stored_eg,ep1)&&Edge_Include(stored_eg,ep2)) { return 1; } } return 0; } void Graph_View(Graph *graph) { Graph_ViewVertexs(graph); Graph_ViewEdges(graph); } void Graph_ViewVertexs(Graph *graph) { Iterator seek = 0, end = 0; Vertex pt = 0; printf("정점 개수:%d\n",graph->vertexs->usage); seek = Array_Begin(graph->vertexs); end = Array_End(graph->vertexs); for(seek = seek; seek != end; ++seek) { pt = (Vertex)(*seek); printf("%s\n",pt); } } void Graph_ViewEdges(Graph *graph) { Iterator seek = 0, end = 0; Edge *edge = 0; printf("간선 개수:%d\n",graph->edges->usage); seek = Array_Begin(graph->edges); end = Array_End(graph->edges); for(seek = seek; seek != end; ++seek) { edge = (Edge *)(*seek); printf("(%s ,%s):%d\n",edge->ep1,edge->ep2,edge->weight); } } void Graph_FindNeighvor(Graph *graph,Vertex ep, Array *neighvor) { Iterator seek = 0, end = 0; Edge *edge = 0; seek = Array_Begin(graph->edges); end = Array_End(graph->edges); for(seek = seek; seek != end; ++seek) { edge = (Edge *)(*seek); if(Edge_Include(edge,ep)) { Vertex opt; opt = Edge_AnOther(edge,ep); Array_PushBack(neighvor,(Element)opt); } } } int Graph_GetWeight(Graph *graph,Vertex ep1, Vertex ep2) { Iterator seek = 0, end = 0; Edge *edge = 0; seek = Array_Begin(graph->edges); end = Array_End(graph->edges); for(seek = seek; seek != end; ++seek) { edge = (Edge *)(*seek); if(Edge_Include(edge,ep1)&&Edge_Include(edge,ep2)) { return edge->weight; } } return -1; }
//Heuristic.h #pragma once #include "Array.h" #include "Graph.h" typedef struct _Heuristic Heuristic; struct _Heuristic { Array *exprs; Graph *graph; Vertex start; Vertex goal; int total_weight; }; Heuristic *MakeInitHeuristic(Graph *graph,Vertex start,Vertex goal); void DeleteHeuristic(Heuristic *now); void FindNextHeuristics(Heuristic *now, Array *next_heus); Vertex GetLastVertex(Heuristic *now); int IsGoal(Heuristic *now); void ViewHeuristic(Heuristic *now);
//Heuristic.c #include "Heuristic.h" #include <malloc.h> #include <string.h> #include <stdio.h> int IsExistVertex(Heuristic *now, Vertex vt) { Iterator seek=0, end=0; Vertex expr_vt; seek = Array_Begin(now->exprs); end = Array_End(now->exprs); for(seek = seek; seek != end; ++seek) { expr_vt = (Vertex)(*seek); if(strcmp(expr_vt,vt)==0) { return 1; } } return 0; } Heuristic *MakeNextHeu(Heuristic *now,Vertex vt) { Heuristic *heu = 0; Iterator seek=0, end=0; Vertex expr_vt; heu = MakeInitHeuristic(now->graph,now->start,now->goal); seek = Array_Begin(now->exprs); end = Array_End(now->exprs); expr_vt = (Vertex)(*seek); for(seek++; seek != end; ++seek) { expr_vt = (Vertex)(*seek); Array_PushBack(heu->exprs,(Element)expr_vt); } heu->total_weight = now->total_weight; heu->total_weight += Graph_GetWeight(heu->graph,expr_vt,vt); Array_PushBack(heu->exprs,(Element)vt); return heu; } Heuristic *MakeInitHeuristic(Graph *graph,Vertex start,Vertex goal) { Heuristic *heu = 0; heu = (Heuristic *)malloc(sizeof(Heuristic)); heu->exprs = New_Array(); heu->graph = graph; heu->start = start; heu->goal = goal; Array_PushBack(heu->exprs,(Element)start); heu->total_weight = 0; return heu; } void DeleteHeuristic(Heuristic *now) { Delete_Array(now->exprs); free(now); } void FindNextHeuristics(Heuristic *now, Array *next_heus) { Array *next_vts = 0; Iterator seek=0, end=0; Vertex next_vt; Heuristic *next; next_vts = New_Array(); Graph_FindNeighvor(now->graph,GetLastVertex(now),next_vts); seek = Array_Begin(next_vts); end = Array_End(next_vts); for(seek = seek; seek != end; ++seek) { next_vt = (Vertex)(*seek); if( !IsExistVertex(now,next_vt) ) { next = MakeNextHeu(now,next_vt); Array_PushBack(next_heus,next); } } } Vertex GetLastVertex(Heuristic *now) { Iterator end = Array_End(now->exprs); --end; return (Vertex)(*end); } int IsGoal(Heuristic *now) { return strcmp(now->goal,GetLastVertex(now))==0; } void ViewHeuristic(Heuristic *now) { Iterator seek=0, end=0; printf("총 거리:%d ",now->total_weight); seek = Array_Begin(now->exprs); end = Array_End(now->exprs); for(seek = seek; seek != end; ++seek) { printf("%s ",(Vertex)*seek); } printf("\n"); }
//Program.c #include <stdio.h> #include "Graph.h" #include "PriorityQueue.h" #include "Heuristic.h" Graph * InitSimulation() { Graph *graph = New_Graph(); Graph_AddVertex(graph,"A"); Graph_AddVertex(graph,"B"); Graph_AddVertex(graph,"C"); Graph_AddVertex(graph,"D"); Graph_AddVertex(graph,"E"); Graph_AddVertex(graph,"F"); Graph_AddVertex(graph,"G"); Graph_AddVertex(graph,"H"); Graph_AddEdge(graph,"A","B",5); Graph_AddEdge(graph,"A","D",4); Graph_AddEdge(graph,"A","E",4); Graph_AddEdge(graph,"B","D",4); Graph_AddEdge(graph,"B","H",2); Graph_AddEdge(graph,"C","D",2); Graph_AddEdge(graph,"C","G",3); Graph_AddEdge(graph,"D","H",5); Graph_AddEdge(graph,"D","E",3); Graph_AddEdge(graph,"D","F",3); Graph_AddEdge(graph,"E","F",3); Graph_AddEdge(graph,"F","G",6); Graph_AddEdge(graph,"G","H",3); Graph_View(graph); return graph; } int CompareHeu(void *v1,void *v2) { Heuristic *h1 = (Heuristic *)v1; Heuristic *h2 = (Heuristic *)v2; return h1->total_weight - h2->total_weight; } int main() { PriQueue *pq = 0; Heuristic *result = 0; Heuristic *heu = 0; Graph *graph = 0; Array *next_heus = 0; Iterator seek=0, end=0; graph = InitSimulation(); pq = New_PriorityQueue(CompareHeu); heu = MakeInitHeuristic(graph,"A","G"); PriQueue_Put(pq,heu); while( ! PriQueue_IsEmpty(pq) ) { heu = (Heuristic *)PriQueue_Get(pq); ViewHeuristic(heu); next_heus = New_Array(); FindNextHeuristics(heu,next_heus); DeleteHeuristic(heu); seek = Array_Begin(next_heus); end = Array_End(next_heus); for(seek=seek; seek != end; ++seek) { heu = (Heuristic *)(*seek); if((result ==0)||(result->total_weight > heu->total_weight)) { if(IsGoal(heu)) { if(result){ DeleteHeuristic(result); } result = heu; } else { PriQueue_Put(pq,heu); } } } Delete_Array(next_heus); } printf("최단 거리\n"); ViewHeuristic(result); Delete_Graph(graph); Delete_PriQueue(pq); return 0; }