You are dropped into a maze with no map. You cannot see the exit, you have no compass pointing the way, and no hint about which corridor is "warmer". All you can do is stand at a junction, notice which turns are available, take one, and repeat — remembering where you've been so you don't wander in circles. Somehow, from nothing but "here are my options", you must find the way out.
That is uninformed search (also called blind search): solving a problem by systematically exploring a space of states using no domain knowledge beyond the bare definition of the problem. The agent cannot tell whether one unexplored state is "closer" to the goal than another — it only knows the goal when it stands on it. That sounds hopeless, yet a handful of blind strategies are guaranteed to find a solution whenever one exists.
This page is about those strategies and, crucially, the one thing that separates them. They differ in a single design choice: the order in which they pull states out of a waiting list. Change that data structure and you change everything — memory, speed, whether the answer is even optimal. Get this frame right and later "informed" methods (like A*) are just this skeleton with a smarter ordering bolted on.
Before you can search, you must say precisely what you are searching. A search problem is defined by five parts:
The initial state, the actions, and the transition model together define a state space — the (possibly enormous) graph of every state reachable from the start. Uninformed search is the art of walking that graph without ever peeking at the map.
Here is the subtlety that trips up almost everyone. The state space is a graph: a state can be reached by many different paths, and paths can loop back on themselves. But a search algorithm unrolls that graph into a search tree, where the root is the initial state and each node is a distinct path the search has considered. Because the same state can sit at the end of many paths, one state in the graph can appear as many nodes in the tree.
If you don't guard against this, the tree balloons far larger than the graph — and if the graph has cycles, the tree becomes infinite. The cure is to keep two collections as you search:
Every strategy on this page shares this exact loop: pop a state off the frontier, test it for the goal, and if it isn't the goal, push its not-yet-seen neighbours onto the frontier. What makes the strategies behave completely differently is one thing only: which end of the frontier we pop from.
Change the frontier's discipline and you change the search:
BFS and DFS are the two you build on top of a plain
Below is a small state space drawn as a search tree, root at the top. BFS expands states in level order: the root first, then everything one step down (left to right), then everything two steps down. The numbers show the order in which BFS visits each node — step through the reveal and watch it sweep across each level before descending.
Notice the shape of the work: to reach depth
Talk is cheap — let's run both on the same tiny graph. The program below stores a graph as an
adjacency list and searches from S to the goal G. BFS
uses a queue (pop the front), DFS uses a stack (pop the back). Press Run and compare
the visit orders: BFS spreads across each level, while DFS dives straight down a branch.
Same graph, same start and goal — but the paths can differ. BFS is guaranteed to return a path with
the fewest edges; DFS returns whatever path its plunge happened to find first, which may be
needlessly long. Delete the if (!(next in parent)) guard and, on a graph with a cycle,
DFS would loop forever — which is exactly the misconception in the next box.
We compare blind strategies on four standard yardsticks, phrased in terms of the branching factor
The trade is stark: BFS buys optimal-depth answers with punishing memory; DFS is memory-thrifty but can wander off forever and returns whatever it stumbles on; UCS pays with a priority queue to earn true cost-optimality.
The classic blunder is to drop the explored / reached set. Without it, your search stops distinguishing the compact state graph from the sprawling search tree: the same state gets re-expanded once for every path that reaches it, and the tree grows exponentially larger than it needs to be. Worse, if the state graph contains a cycle, a tree-style search with no memory of where it has been will loop through that cycle forever — never terminating even though a solution sits nearby.
This bites DFS hardest, and it's the reason DFS is not complete on infinite or looping spaces: it can plunge down an endless branch and never come back. Always track reached states (or, at minimum, avoid revisiting states already on the current path). And keep the two failings of DFS straight in your head: it is neither optimal (it returns the first path it finds, however long) nor, without cycle-checking, complete.
Because BFS's real enemy is memory, not time. People often assume the
With branching factor