数据结构和算法设计(迷宫求解问题的栈和队列的实现)
2011-10-05 21:34
896 查看
此问题中,迷宫用一个二位数组data[ ][ ]表示,data[i][j]的值为0,则表示该点为通路;如果为1,则表示该点为障碍;如果为-1,则表示该点已经走过。数组的四周值都为1,表示边界。给定起点和终点,求起点到终点的路径。
可以使用栈对二维数组进行深度优先搜索,直到找到终点的时候停止搜索。此方案找到的路径不一定是最短路径。如果要好到最短路径,可以使用队列来进行二维数组的宽度优秀搜索,直到找到终点停止搜索,然后从队列中找出我们需要的最短路径。废话少说,代码如下:
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class Maze {
private int[][] data = null;//数据1:障碍,0:出路,-1:此点已经通过
private Stack<Point> stack = new Stack<Point>() ;
private List<Point> queue = new ArrayList<Point>() ;//用数组模拟队列操作
public Maze(int[][] data){ //出使化
this.data = data ;
}
public boolean getPath(Point start , Point end){
boolean isFind = false ;//是否找到
Point temp = null;
stack.push(start) ;//将起点入栈
this.data[start.getX()][start.getY()] = -1 ;//起点标记为走过
while(!stack.isEmpty()){//栈不为空时进入循环
temp = stack.lastElement() ;//得到栈顶元素
int x = temp.getX() ;
int y = temp.getY() ;
int di = temp.getDirection() ;//得到方向
if(temp.equals(end)){//找到终点
printPath() ;
return true ;
}
isFind = false ;
while(di<4 && !isFind){//当方向没有找完,而且没有找到
di++ ;//下一个方向寻找
switch(di){
case 0: x = temp.getX() - 1 ; y = temp.getY() ; break ;//向上
case 1: x = temp.getX() ; y = temp.getY() + 1 ; break ;//向右
case 2: x = temp.getX() + 1 ; y = temp.getY() ; break ;//向下
case 3: x = temp.getX() ; y = temp.getY() - 1 ; break ;//向左
default : break ;
}
if(this.data[x][y] == 0){//如果找到则跳出循环
isFind = true ;
}
}
if(isFind){//如果找到了出路,则将此节点入栈
stack.lastElement().setDirection(di) ;//设置上一个节点的方向
Point p = new Point(x , y , -1) ;//新节点入栈
stack.push(p) ;
this.data[x][y] = -1 ;//将当前节点标记为障碍
}else{//如果没有找到节点
Point p = stack.pop() ;//出栈
this.data[p.getX()][p.getY()] = 0 ;//当前节点标记为通路
}
}
return false ;
}
public boolean getPath2(Point start, Point end){//使用队列找到起点到终点的最短路径
int index = -1 ;//队列中下标值
Point temp = null ;
boolean isFind = false ;
int x=-1 , y=-1 , di=-1 ;
queue.add(start) ;//起点入队列
this.data[start.getX()][start.getY()] = - 1 ; //起点标记为走过
while(!queue.isEmpty() && !isFind){
index++ ;
temp = queue.get(index) ;//得到队列中寻找的节点
if(temp.equals(end)){
printPath2(index) ;//index为终点在队列中的下标值
return true ;
}
isFind = false ;
for(di = 0 ; di<4 ; di++){
switch(di){
case 0: x = temp.getX() - 1 ; y = temp.getY() ; break ;//向上
case 1: x = temp.getX() ; y = temp.getY() + 1 ; break ;//向右
case 2: x = temp.getX() + 1 ; y = temp.getY() ; break ;//向下
case 3: x = temp.getX() ; y = temp.getY() - 1 ; break ;//向左
default : break ;
}
if(this.data[x][y] == 0){//节点是通路
queue.add(new Point(x , y , index)) ;
this.data[x][y] = -1 ;//将此点标记为走过
}
}
}
return false ;
}
public void printPath(){
for(int i=0 ; i<stack.size() ; i++){
Point p = stack.get(i) ;
System.out.println("[" + p.getX() + "," + p.getY() + "]");
}
}
public void printPath2(int x){
int index = x ;//终点在队列中的下标
while(index != -1){
int pre = queue.get(index).getDirection() ;//得到前一个点的下标
queue.get(index).setDirection(-1) ;//将我们需要的路径上的点的前驱置为-1
index = pre ;
}
for(int i=0,len=queue.size() ; i<len ; i++){
Point p = queue.get(i) ;
if(p.getDirection() == -1){
System.out.println("[" + p.getX() + "," + p.getY() + "]");
}
}
}
public static void main(String[] args) {
int mg[][] = //定义迷宫,0代表通路,1代表障碍
{ {1,1,1,1,1,1,1,1,1,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,0,0,1,1,0,0,1},
{1,0,1,1,1,0,0,0,0,1},
{1,0,0,0,1,0,0,0,0,1},
{1,0,1,0,0,0,1,0,0,1},
{1,0,1,1,1,0,1,1,0,1},
{1,1,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1}
};
Maze m = new Maze(mg) ;
Point p1 = new Point(1 , 1 ) ;
Point p2 = new Point(8 , 8 ) ;
// m.getPath(p1 , p2) ;
m.getPath2(p1 , p2) ;
}
}
在此类中用到了一个辅助类Point,代码如下:
package edu.qc.stack;
public class Point {
private int x;
private int y;
private int direction;//如果使用栈,此变量代表从此点经过时候的方向,0:上,1:右,2:下,3:左;如果使用队列,则此变量代表路径中此点的前一个节点在队列中的下标值
public Point(){
this.x = 0 ;
this.y = 0 ;
this.direction = -1 ;
}
public Point(int x , int y){
this.x = x ;
this.y = y ;
this.direction = -1 ;
}
public Point(int x , int y , int direction){
this.x = x ;
this.y = y ;
this.direction = direction ;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getDirection() {
return direction;
}
public void setDirection(int direction) {
this.direction = direction;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof Point){
Point p = (Point)obj ;
if((p.getX() == this.x) && (p.getY() == this.y)){
return true ;
}else{
return false ;
}
}
return false ;
}
@Override
public int hashCode() {
return super.hashCode() + x + y;
}
}
可以使用栈对二维数组进行深度优先搜索,直到找到终点的时候停止搜索。此方案找到的路径不一定是最短路径。如果要好到最短路径,可以使用队列来进行二维数组的宽度优秀搜索,直到找到终点停止搜索,然后从队列中找出我们需要的最短路径。废话少说,代码如下:
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class Maze {
private int[][] data = null;//数据1:障碍,0:出路,-1:此点已经通过
private Stack<Point> stack = new Stack<Point>() ;
private List<Point> queue = new ArrayList<Point>() ;//用数组模拟队列操作
public Maze(int[][] data){ //出使化
this.data = data ;
}
public boolean getPath(Point start , Point end){
boolean isFind = false ;//是否找到
Point temp = null;
stack.push(start) ;//将起点入栈
this.data[start.getX()][start.getY()] = -1 ;//起点标记为走过
while(!stack.isEmpty()){//栈不为空时进入循环
temp = stack.lastElement() ;//得到栈顶元素
int x = temp.getX() ;
int y = temp.getY() ;
int di = temp.getDirection() ;//得到方向
if(temp.equals(end)){//找到终点
printPath() ;
return true ;
}
isFind = false ;
while(di<4 && !isFind){//当方向没有找完,而且没有找到
di++ ;//下一个方向寻找
switch(di){
case 0: x = temp.getX() - 1 ; y = temp.getY() ; break ;//向上
case 1: x = temp.getX() ; y = temp.getY() + 1 ; break ;//向右
case 2: x = temp.getX() + 1 ; y = temp.getY() ; break ;//向下
case 3: x = temp.getX() ; y = temp.getY() - 1 ; break ;//向左
default : break ;
}
if(this.data[x][y] == 0){//如果找到则跳出循环
isFind = true ;
}
}
if(isFind){//如果找到了出路,则将此节点入栈
stack.lastElement().setDirection(di) ;//设置上一个节点的方向
Point p = new Point(x , y , -1) ;//新节点入栈
stack.push(p) ;
this.data[x][y] = -1 ;//将当前节点标记为障碍
}else{//如果没有找到节点
Point p = stack.pop() ;//出栈
this.data[p.getX()][p.getY()] = 0 ;//当前节点标记为通路
}
}
return false ;
}
public boolean getPath2(Point start, Point end){//使用队列找到起点到终点的最短路径
int index = -1 ;//队列中下标值
Point temp = null ;
boolean isFind = false ;
int x=-1 , y=-1 , di=-1 ;
queue.add(start) ;//起点入队列
this.data[start.getX()][start.getY()] = - 1 ; //起点标记为走过
while(!queue.isEmpty() && !isFind){
index++ ;
temp = queue.get(index) ;//得到队列中寻找的节点
if(temp.equals(end)){
printPath2(index) ;//index为终点在队列中的下标值
return true ;
}
isFind = false ;
for(di = 0 ; di<4 ; di++){
switch(di){
case 0: x = temp.getX() - 1 ; y = temp.getY() ; break ;//向上
case 1: x = temp.getX() ; y = temp.getY() + 1 ; break ;//向右
case 2: x = temp.getX() + 1 ; y = temp.getY() ; break ;//向下
case 3: x = temp.getX() ; y = temp.getY() - 1 ; break ;//向左
default : break ;
}
if(this.data[x][y] == 0){//节点是通路
queue.add(new Point(x , y , index)) ;
this.data[x][y] = -1 ;//将此点标记为走过
}
}
}
return false ;
}
public void printPath(){
for(int i=0 ; i<stack.size() ; i++){
Point p = stack.get(i) ;
System.out.println("[" + p.getX() + "," + p.getY() + "]");
}
}
public void printPath2(int x){
int index = x ;//终点在队列中的下标
while(index != -1){
int pre = queue.get(index).getDirection() ;//得到前一个点的下标
queue.get(index).setDirection(-1) ;//将我们需要的路径上的点的前驱置为-1
index = pre ;
}
for(int i=0,len=queue.size() ; i<len ; i++){
Point p = queue.get(i) ;
if(p.getDirection() == -1){
System.out.println("[" + p.getX() + "," + p.getY() + "]");
}
}
}
public static void main(String[] args) {
int mg[][] = //定义迷宫,0代表通路,1代表障碍
{ {1,1,1,1,1,1,1,1,1,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,0,0,1,1,0,0,1},
{1,0,1,1,1,0,0,0,0,1},
{1,0,0,0,1,0,0,0,0,1},
{1,0,1,0,0,0,1,0,0,1},
{1,0,1,1,1,0,1,1,0,1},
{1,1,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1}
};
Maze m = new Maze(mg) ;
Point p1 = new Point(1 , 1 ) ;
Point p2 = new Point(8 , 8 ) ;
// m.getPath(p1 , p2) ;
m.getPath2(p1 , p2) ;
}
}
在此类中用到了一个辅助类Point,代码如下:
package edu.qc.stack;
public class Point {
private int x;
private int y;
private int direction;//如果使用栈,此变量代表从此点经过时候的方向,0:上,1:右,2:下,3:左;如果使用队列,则此变量代表路径中此点的前一个节点在队列中的下标值
public Point(){
this.x = 0 ;
this.y = 0 ;
this.direction = -1 ;
}
public Point(int x , int y){
this.x = x ;
this.y = y ;
this.direction = -1 ;
}
public Point(int x , int y , int direction){
this.x = x ;
this.y = y ;
this.direction = direction ;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getDirection() {
return direction;
}
public void setDirection(int direction) {
this.direction = direction;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof Point){
Point p = (Point)obj ;
if((p.getX() == this.x) && (p.getY() == this.y)){
return true ;
}else{
return false ;
}
}
return false ;
}
@Override
public int hashCode() {
return super.hashCode() + x + y;
}
}
相关文章推荐
- 数据结构:栈和队列-迷宫问题求解
- 算法设计和数据结构学习_4(《数据结构和问题求解》part4笔记)
- 算法设计和数据结构学习_3(《数据结构和问题求解》part2笔记)
- 算法设计和数据结构学习_3(《数据结构和问题求解》part2笔记)
- 基因表达式编程的任务指派问题求解算法设计与实现
- 基因表达式编程的任务指派问题求解算法设计与实现
- 算法与数据结构题目的 PHP 实现:栈和队列 设计一个有 getMin 功能的栈
- 基因表达式编程的任务指派问题求解算法设计与实现
- 迷宫问题算法设计与实现
- 算法设计和数据结构学习_4(《数据结构和问题求解》part4笔记)
- 基因表达式编程的任务指派问题求解算法设计与实现
- 用递归法:设计算法求解汉诺塔问题,并编程实现。 (1) Hanoi(汉诺)塔问题分析 这是一个古典的数学问题,是一个用递归方法解题的典型例子。问题是这样的:古代有一个梵塔,塔内有3个座 A,B,C
- 基因表达式编程的任务指派问题求解算法设计与实现
- 蛮力法:设计算法求解字符串的模式匹配问题,并编程实现。
- 约瑟夫问题求解算法的设计与实现
- 蛮力法:设计算法求解背包问题,并编程实现。
- 中国象棋程序的设计与实现(六)--N皇后问题的算法设计与实现(源码+注释+截图)
- 用栈和队列实现迷宫求解
- 用栈和队列求解迷宫问题
- java数据结构与算法之(Queue)队列设计与实现