Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Add the A* algorithm.#35

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
zjl9959 wants to merge1 commit intoalgorithm-visualizer:master
base:master
Choose a base branch
Loading
fromzjl9959:AStarPathFinding
Open
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletionsBranch and Bound/AStar Path Finding/README.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
# AStar path finding

<img src="https://cdn.jsdelivr.net/gh/zjl9959/algviz-launch@master/svgs/AStarPathFinding_sec.svg" width=240px/>

AStar(A*) is an effective path-finding algorithm for a grid map (such as a 2D maze).
A* algorithm uses breadth-first search as the basic framework, but it uses a priority queue to sort the point to be explored. The algorithm will explore the point in the front of the priority queue first.

The key of the priority queue is the `hamiltonDistance(start, candidate) + hamiltonDistance(candidate, end)` and the value is the candidate point. The keys in the priority queue are heuristic information to guide the algorithm to explore the points that are more likely to be on the shortest path. So A* algorithm is more effective than the breadth-first search algorithm.

## Complexity

**Time Complexity:** `O(R·C)` for the worst case, `O(R + C)` for the best case.

**Space Complexity:** `O(R·C) ~ O(R + C)` cost by the priority queue.

*`R` is the grid map's row number and `C` is the grid map's column number.*

## Reference

+ [redblobgames - introduction to the A* Algorithm](https://www.redblobgames.com/pathfinding/a-star/introduction.html)
+ [algviz - an algorithm animation engine for Python](https://github.com/zjl9959/algviz-launch)
133 changes: 133 additions & 0 deletionsBranch and Bound/AStar Path Finding/code.js
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
// import visualization libraries {
const { Tracer, Array2DTracer, Array1DTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
// }

// define map information. {
const row = 10;
const col = 10;
let map = [
['', '', '', '', '', '', '', '', '', ''], // 0
['', '', '💣', '', '', '', '', '', '', ''], // 1
['', 'S', '', '💣', '', '', '', '', '', ''], // 2
['', '', '', '💣', '', '', '', '', '', ''], // 3
['', '', '', '', '', '💣', '', '', '', ''], // 4
['', '', '', '', '💣', '💣', '', '', '', ''], // 5
['', '', '', '', '', '💣', '', '', '', ''], // 6
['', '', '', '', '', '', '💣', '', 'E', ''], // 7
['', '', '', '', '', '', '💣', '', '', ''], // 8
['', '', '', '', '', '', '', '', '', ''] // 9
];
const start = [2, 1];
const end = [7, 8];
let pqueue = [start];
let que_keys = [0];
let visit = new Set();
// }

// define tracer variables {
const mapTracer = new Array2DTracer('Map');
const priorityQueueTracer = new Array1DTracer('PriorityQueue-key');
Layout.setRoot(new VerticalLayout([mapTracer, priorityQueueTracer]));

mapTracer.set(map);
priorityQueueTracer.set(que_keys);
Tracer.delay();
// }

function hamiltonDistance(pos1, pos2) {
return Math.abs(pos1[0]-pos2[0]) + Math.abs(pos1[1]-pos2[1]);
}

function insertQueue(que_keys, k, v) {
let put = false;
que_keys.push(0); pqueue.push(0);
if (que_keys.length > 1) {
for (let i = que_keys.length - 2; i >= 0; i--) {
if (k < que_keys[i]) {
pqueue[i+1] = v;
que_keys[i+1] = k;
put = true;
priorityQueueTracer.patch(i+1, k);
break;
} else {
pqueue[i+1] = pqueue[i];
que_keys[i+1] = que_keys[i];
priorityQueueTracer.patch(i+1, que_keys[i]);
}
}
}
if (put === false) {
que_keys[0] = k;
pqueue[0] = v;
priorityQueueTracer.patch(0, k);
}
}

function isEnd(pos) { return pos[0] == end[0] && pos[1] == end[1]; }

function isBlock(pos) {
return map[pos[0]][pos[1]] === '💣';
}

function isVisited(pos) {
return visit.has(pos[0]*col + pos[1]);
}

function findPath() {
while (pqueue.length > 0) {
let cur = pqueue.pop(); que_keys.pop();
if (isEnd(cur)) break;
if (isVisited(cur)) continue;
visit.add(cur[0]*col + cur[1]);
let up = [cur[0]-1, cur[1]];
let down = [cur[0]+1, cur[1]];
let left = [cur[0], cur[1]-1];
let right = [cur[0], cur[1]+1];
let cur_dist = hamiltonDistance(cur, start);
if (up[0] >= 0 && !isVisited(up) && !isBlock(up)) {
let dist = cur_dist + hamiltonDistance(up, end);
insertQueue(que_keys, dist, up);
map[up[0]][up[1]] = '↓';
// visualize {
if (!isEnd(up)) {
mapTracer.patch(up[0], up[1], '↓');
}
// }
}
if (down[0] < row && !isVisited(down) && !isBlock(down)) {
let dist = cur_dist + hamiltonDistance(down, end);
insertQueue(que_keys, dist, down);
map[down[0]][down[1]] = '↑';
// visualize {
if (!isEnd(down)) {
mapTracer.patch(down[0], down[1], '↑');
}
// }
}
if (left[1] >= 0 && !isVisited(left) && !isBlock(left)) {
let dist = cur_dist + hamiltonDistance(left, end);
insertQueue(que_keys, dist, left);
map[left[0]][left[1]] = '→';
// visualize {
if (!isEnd(left)) {
mapTracer.patch(left[0], left[1], '→');
}
// }
}
if (right[1] < col && !isVisited(right) && !isBlock(right)) {
let dist = cur_dist + hamiltonDistance(right, end);
insertQueue(que_keys, dist, right);
map[right[0]][right[1]] = '←';
// visualize {
if (!isEnd(right)) {
mapTracer.patch(right[0], right[1], '←');
}
// }
}
// visualize {
Tracer.delay();
// }
}
}

findPath();

[8]ページ先頭

©2009-2025 Movatter.jp