An uninformed (a.k.a. blind, brute-force) search algorithm generates the search tree without using any domain specific knowledge.
The two basic approaches differ as to whether you check for a goal when a node is generated or when it is expanded.
Checking at generation time:
if start_state is a goal state return the empty action list
fringe := [make_node(start_state, null, null)]
while fringe is not empty
n := select and remove some node from the fringe
for each action a applicable to n.state
s := succ(n.state, a)
n' := make_node(s, a, n)
if s is a goal state, return n'.actionListFromRoot()
add n' to fringe
return failure
Checking at expansion time:
fringe := [make_node(start_state, null, null)]
while fringe is not empty
n := select and remove some node from the fringe
if n.state is a goal state return n.actionListFromRoot()
for each action a applicable to n.state
add make_node(succ(n.state, a), a, n) to fringe
return failure
Strategy: expand the shallowest unexpanded node. Implementation: The fringe is a FIFO queue.
For this search tree

The queue evolves like this
A
B C D
C D E F
D E F G H I
E F G H I J
F G H I J K L
G H I J K L M
H I J K L M
I J K L M N O
J K L M N O
K L M N O P Q
L M N O P Q
M N O P Q
N O P Q
O P Q
P Q R S T
Q R S T
R S T U
S T U
T U V
U V
V
That is, the order of generation is ABCDEFGHIJKLMNOPQRSTUV and the order of expansion is the same.
If the goal nodes were M, V, and J, Breadth-First search would find J, the shallowest.
BFS
Strategy: expand the deepest unexpanded node. Implementation: The fringe is a LIFO queue (stack)
For the search tree above:
A B C D E F C D K L F C D L F C D F C D M C D C D G H I D H I D N O I D O I D R S T I D S T I D V T I D T I D I D D J P Q Q U
If the goal nodes were M, V, and J, the Depth-First search above would find M.
DFS
This is just a depth-first search with a cutoff depth. Here is the algorithm (for the test-at-expansion-time case)
fringe := [make_node(start_state, null, null)]
reached_limit := false
while fringe is not empty
n := fringe.pop()
if n.state is a goal state return n.actionListFromRoot()
if n.depth == limit
reached_limit := true
else
for each action a applicable to n.state
fringe.push(make_node(succ(n.state, a), a, n))
return reached_limit ? cutoff : failure
DLS
Algorithm:
for i in 1..infinity
run DLS to level i
if found a goal at level i, return it immediately
DFID
Strategy: Expand the lowest cost node. Implementation: the fringe is a priority queue: lowest cost node has the highest priority. In order to be optimal, must test at expansion, not generation, time.
Run the search backwards from a goal state to a start state. Obiously this works best when the actions are reversible, and the set of goal states is small.
Run a search forward from the start state and simulatneously. Motivation is that $b^{\frac{d}{2}} + b^{\frac{d}{2}}$ is much, much less than $b^d$. Works best when the backwards search is feasible. Problem is space complexity: one of the trees has to be kept in memory so we can test membership for a node generated in the other tree.