diff --git a/Graphs/Astar.js b/Graphs/Astar.js
new file mode 100644
index 0000000000..fc20f6e79b
--- /dev/null
+++ b/Graphs/Astar.js
@@ -0,0 +1,207 @@
+/**
+ * @author : Mathang Peddi
+ * A* Algorithm calculates the minimum cost path between two nodes.
+ * It is used to find the shortest path using heuristics.
+ * It uses graph data structure.
+ */
+
+// Euclidean distance heuristic for 2D points
+function euclideanHeuristic(pointA, pointB) {
+  const dx = pointA[0] - pointB[0]
+  const dy = pointA[1] - pointB[1]
+  return Math.sqrt(dx * dx + dy * dy)
+}
+
+// Priority Queue (Min-Heap) implementation
+class PriorityQueue {
+  constructor() {
+    this.elements = []
+  }
+
+  enqueue(node, priority) {
+    this.elements.push({ node, priority })
+    this.bubbleUp()
+  }
+
+  bubbleUp() {
+    let index = this.elements.length - 1
+    while (index > 0) {
+      let parentIndex = Math.floor((index - 1) / 2)
+      if (this.elements[index].priority >= this.elements[parentIndex].priority)
+        break
+      ;[this.elements[index], this.elements[parentIndex]] = [
+        this.elements[parentIndex],
+        this.elements[index]
+      ]
+      index = parentIndex
+    }
+  }
+
+  dequeue() {
+    if (this.elements.length === 1) {
+      return this.elements.pop().node
+    }
+
+    const node = this.elements[0].node
+    this.elements[0] = this.elements.pop()
+    this.sinkDown(0)
+    return node
+  }
+
+  sinkDown(index) {
+    const length = this.elements.length
+    const element = this.elements[index]
+    while (true) {
+      let leftChildIndex = 2 * index + 1
+      let rightChildIndex = 2 * index + 2
+      let swapIndex = null
+
+      if (
+        leftChildIndex < length &&
+        this.elements[leftChildIndex].priority < element.priority
+      ) {
+        swapIndex = leftChildIndex
+      }
+
+      if (
+        rightChildIndex < length &&
+        this.elements[rightChildIndex].priority <
+          (swapIndex === null
+            ? element.priority
+            : this.elements[leftChildIndex].priority)
+      ) {
+        swapIndex = rightChildIndex
+      }
+
+      if (swapIndex === null) break
+      ;[this.elements[index], this.elements[swapIndex]] = [
+        this.elements[swapIndex],
+        this.elements[index]
+      ]
+      index = swapIndex
+    }
+  }
+
+  isEmpty() {
+    return this.elements.length === 0
+  }
+}
+
+function aStar(graph, src, target, points) {
+  const openSet = new PriorityQueue() // Priority queue to explore nodes
+  openSet.enqueue(src, 0)
+
+  const cameFrom = Array(graph.length).fill(null) // Keep track of path
+  const gScore = Array(graph.length).fill(Infinity) // Actual cost from start to a node
+  gScore[src] = 0
+
+  const fScore = Array(graph.length).fill(Infinity) // Estimated cost from start to goal (g + h)
+  fScore[src] = euclideanHeuristic(points[src], points[target])
+
+  while (!openSet.isEmpty()) {
+    // Get the node in openSet with the lowest fScore
+    const current = openSet.dequeue()
+
+    // If the current node is the target, reconstruct the path and return
+    if (current === target) {
+      const path = []
+      while (cameFrom[current] !== -1) {
+        path.push(current)
+        current = cameFrom[current]
+      }
+      path.push(src)
+      return path.reverse()
+    }
+
+    // Explore neighbors using destructuring for cleaner code
+    for (const [neighbor, weight] of graph[current]) {
+      const tentative_gScore = gScore[current] + weight
+
+      if (tentative_gScore < gScore[neighbor]) {
+        cameFrom[neighbor] = current
+        gScore[neighbor] = tentative_gScore
+        const priority =
+          gScore[neighbor] +
+          euclideanHeuristic(points[neighbor], points[target])
+        fScore[neighbor] = priority
+
+        openSet.enqueue(neighbor, priority)
+      }
+    }
+  }
+
+  return null // Return null if there's no path to the target
+}
+
+// Define the graph as an adjacency list
+const graph = [
+  [
+    [1, 4],
+    [7, 8]
+  ], // Node 0 connects to node 1 (weight 4), node 7 (weight 8)
+  [
+    [0, 4],
+    [2, 8],
+    [7, 11]
+  ], // Node 1 connects to node 0, node 2, node 7
+  [
+    [1, 8],
+    [3, 7],
+    [5, 4],
+    [8, 2]
+  ], // Node 2 connects to several nodes
+  [
+    [2, 7],
+    [4, 9],
+    [5, 14]
+  ], // Node 3 connects to nodes 2, 4, 5
+  [
+    [3, 9],
+    [5, 10]
+  ], // Node 4 connects to nodes 3 and 5
+  [
+    [2, 4],
+    [3, 14],
+    [4, 10],
+    [6, 2]
+  ], // Node 5 connects to several nodes
+  [
+    [5, 2],
+    [7, 1],
+    [8, 6]
+  ], // Node 6 connects to nodes 5, 7, 8
+  [
+    [0, 8],
+    [1, 11],
+    [6, 1],
+    [8, 7]
+  ], // Node 7 connects to several nodes
+  [
+    [2, 2],
+    [6, 6],
+    [7, 7]
+  ] // Node 8 connects to nodes 2, 6, 7
+]
+
+// Define 2D coordinates for each node (these can be changed based on actual node positions)
+const points = [
+  [0, 0], // Point for node 0
+  [1, 2], // Point for node 1
+  [2, 1], // Point for node 2
+  [3, 5], // Point for node 3
+  [4, 3], // Point for node 4
+  [5, 6], // Point for node 5
+  [6, 8], // Point for node 6
+  [7, 10], // Point for node 7
+  [8, 12] // Point for node 8
+]
+
+// Call the aStar function with the graph, source node (0), and target node (4)
+const path = aStar(graph, 0, 4, points)
+
+console.log('Shortest path from node 0 to node 4:', path)
+
+/**
+ * The function returns the optimal path from the source to the target node.
+ * The heuristic used is Euclidean distance between nodes' 2D coordinates.
+ */