algorithm path search

simuruk wiki

BFS

  • breadth first search 너비탐색
int n; // 입력되는 정점의 최댓값
int rear, front; // 전단과 후단을 나타내는 변수
int map[30][30], queue[30], visit[30]; // 인접 행렬과 큐와 방문 배열
 
void BFS(int v)
{
    int i;
 
    visit[v] = 1; // 정점 v를 방문했다고 표시
    printf(""%d에서 시작\n"", v);
    queue[rear++] = v; // 큐에 v를 삽입하고 후단을 1 증가시킴
    while (front < rear) // 후단이 전단과 같거나 작으면 루프 탈출
    {
        // 큐의 첫번째에 있는 데이터를 제외하고 값을 가져오며, 전단 1 증가
        v = queue[front++];
        for (i = 1; i <= n; i++)
        {
            // 정점 v와 정점 i가 만나고, 정점 i를 방문하지 않은 상태일 경우
            if (map[v][i] == 1 && !visit[i])
            {
                visit[i] = 1; // 정점 i를 방문했다고 표시
                printf(""%d에서 %d로 이동\n"", v, i);
                queue[rear++] = i; // 큐에 i를 삽입하고 후단을 1 증가시킴
            }
        }
    }
}

Queue que = new Queue();
root.marked = true;
que.enqueue(root);
while(!que.isEmpty()){
    Node r = que.dequeue();
    visit®;
    foreach(Node n in r.adjacent){
        if(n.marked==false){
            n.marked = true;
            que.enqueue(n);
        }
    }
}

DFS

  • depth first search 깊이 탐색
int n; // 정점의 총 갯수
int map[30][30], visit[30]; // 인접 행렬과 방문 여부
void DFS(int v)
{
    int i;
 
    visit[v] = 1; // 정점 v를 방문했다고 표시
    for (i = 1; i <= n; i++)
    {
        // 정점 v와 정점 i가 연결되었고, 정점 i를 방문하지 않았다면
        if (map[v][i] == 1 && !visit[i])
        {
            printf(""%d에서 %d로 이동\n"", v, i);
            // 정점 i에서 다시 DFS를 시작한다
            DFS(i);
        }
    }
}

if(root==null)return;
visit(root);
root.visited=true;
foreach(Node n in root.adjacent){
    if(n,visit == false){
        search(n);
    }
}

binary tree

// 전위 중 왼 오른 - 루트가 먼저 출력
// 중위 왼 중 오른 - 루트가 중간
// 후위 왼 오 중 - 루트가 마지막
// 레벨 큐 이용 전부 큐에 넣고 출력 그냥 줄대로 나옴
class Node:
    def __init__(self, val):
        self.val = val
        self.leftChild = None
        self.rightChild = None

class BinarySearchTree:
    def __init__(self):
        self.root = None

    def setRoot(self, val):
        self.root = Node(val)"	"def insert(self, val):
        if (self.root is None):
            self.setRoot(val)
        else:
            self.insertNode(self.root, val)

    def insertNode(self, currentNode, val):
        if (val <= currentNode.val):
            if (currentNode.leftChild):
                self.insertNode(currentNode.leftChild, val)
            else:
                currentNode.leftChild = Node(val)
        elif (val > currentNode.val):
            if (currentNode.rightChild):
                self.insertNode(currentNode.rightChild, val)
            else:
                currentNode.rightChild = Node(val)"	"def traverse(self):
        return self.traverseNode(self.root)

    def traverseNode(self, currentNode):
        result = []
        if (currentNode.leftChild is not None):
           result.extend(self.traverseNode(currentNode.leftChild))
        if (currentNode is not None):
            result.extend([currentNode.val])
        if (currentNode.rightChild is not None):
            result.extend(self.traverseNode(currentNode.rightChild))
        return result

dijkstra

다익스트라 F = G+H 비용 시작점과 새로운점 이동비용 얻어진 사각형으로부터 대각선을 포함하지 않는 목표까지 이동거리

// 정점의 개수
  int V;
  // 그래프의 인접 리스트. (연결된 정점 번호, 간선 가중치) 쌍을 담는다.
  vector<pair<int, int> > adj[MAX_V];

  vector<int> dijkstra(int src) {
    vector<int> dist(V, INF);
    dist[src] = 0;
    priority_queue<pair<int, int> > pq;
    pq.push(make_pair(0, src));

    while (!pq.empty()) {
      int cost = -pq.top().first;
      int here = pq.top().second;
      pq.pop();
// 만약 지금 꺼낸 것보다 더 짧은 경로를 알고 있다면 지금 꺼낸 것을 무시한다.
      if (dist[here] < cost) continue;

      // 인접한 정점들을 모두 검사한다.
      for (int i = 0; i < adj[here].size(); ++i) {
        int there = adj[here][i].first;
        int nextDist = cost + adj[here][i].second;
        // 더 짧은 경로를 발견하면, dist[]를 갱신하고 우선순위 큐에 넣는다.
        if (dist[there] > nextDist) {
          dist[there] = nextDist;
          pq.push(make_pair(-nextDist, there));
        }
      }
    }

    return dist;
  }

astar

function A*(start, goal)
// 이미 실행했던 노드들 '닫힌 목록’
closedSet := {}
// 아직 실행하지 않았지만 이제 탐색할 노드들 ‘열린 목록’
// 초기에는, 시작 노드만 들어있습니다.
openSet := {start}
// 각가장 효율적인 경로를(노드들을) 담습니다.
cameFrom := the empty map
// 각 노드별 시작 노드로부터의 거리를 담습니다. (기본 비용은 Infinity, 최소비용을 찾는 것이므로)
gScore := map with default value of Infinity
// 처음 노드는 시작 노드이므로 gScore는 0입니다.
gScore[start] := 0
// 시작 노드로부터의 비용, 목적 노드까지의 비용 두 가지가 합산된 비용입니다.
fScore := map with default value of Infinity

// 첫 번째 노드는 시작 노드로부터의 비용이 0이고, 목적 노드까지는 heuristic한 추정 비용입니다.
// 그러므로, 첫 노드의 전체 비용은 추정값만 있을 뿐 입니다.
fScore[start] := heuristic_cost_estimate(start, goal)
// '열린 목록’이 비어있을 때까지 반복합니다.
while openSet is not empty
// '열린 목록’에서 가장 적은 f값을 가지는 노드
current := the node in openSet having the lowest fScore[] value
// 목적 노드입니까?
if current = goal
// 길 찾기를 완료하였으니 경로를 만듭니다.
return reconstruct_path(cameFrom, current)
// 목적노드가 아니라면 '열린 목록’에서 삭제하고 '닫힌 목록’에 넣습니다.
openSet.Remove(current)
closedSet.Add(current)
// 최소 비용으로 선택한 노드의 인접 노드들을 바라봅니다.
for each neighbor of current”	" // 인접 노드가 이미 '닫힌 목록’에 들어있다면 무시하고 넘어갑니다. (이미 실행해 본것이므로)
if neighbor in closedSet
continue
// '열린 목록’에 들어있지 않다면 추가합니다.
if neighbor not in openSet
openSet.Add(neighbor)
// current 노드까지의 gScore + current 노드로부터 인접 노드까지 거리를 구합니다.
// 시작 노드로부터 인접 노드까지 gScore가 current 노드를 거쳐
// 인접 노드까지 가는 비용보다 싸다면 이 경로는 무시합니다.
tentative_gScore := gScore[current] + dist_between(current, neighbor)
if tentative_gScore >= gScore[neighbor]
continue
// current 노드를 거쳐서 가는 것이 더 좋다고 생각되면 기록합니다.
cameFrom[neighbor] := current
gScore[neighbor] := tentative_gScore
fScore[neighbor] := gScore[neighbor] + heuristic_cost_estimate(neighbor, goal)
return failure
function reconstruct_path(cameFrom, current)
total_path := [current]
while current in cameFrom.Keys:
current := cameFrom[current]
total_path.append(current)
return total_path