一:棧
1.棧的應用背景
棧是一種線性數據結構,並且只能在某一端存數據和取數據。
關鍵詞:先進先出。
2.棧的兩種實現方法:
2.1用ArrayList實現棧
具體代碼如下:
import java.util.ArrayList;
public class ArrayListAsStack {
ArrayList stack = new ArrayList();
public ArrayListAsStack(int n){
stack.ensureCapacity(n);
}
public void push(Object o1){
stack.add(o1);
}
public Object pop(){
return stack.remove(stack.size()-1);
}
public Object topEle(){
return stack.get(stack.size()-1);
}
public boolean isEmpty(){
return stack.isEmpty();
}
public void clean(){
stack.clear();
}
}
Pop:只用刪除ArrayList中的最後一個元素
Push:在ArrayList中添加一個元素
2.2用LinkedList實現棧
代碼如下:
import java.util.LinkedList;
public class LinkedListAsStack {
LinkedList stack = new LinkedList();
public void push(Object o1){
stack.add(o1);
}
public Object pop(){
return stack.removeLast();
}
public Object topEle(){
return stack.getLast();
}
public boolean isEmpty(){
return stack.isEmpty();
}
public void clean(){
stack.clear();
}
}
Pop:刪除鏈表中最後一個節點
Push:在鏈表中添加一個節點
二:隊列
隊列與棧的不同之處在於,隊列的兩端都有用到,數據從隊列的尾部添加,從隊列的頭部取出。FIFO原則。
1.隊列的實現
與棧相同,隊列可以通過array和linkedlist兩種方式實現,在此不再累述。
2.優先隊列
隊列的先進先出有時候會有一定的侷限性。例如:銀行辦業務的客戶必須按照“先進先出”的性質進行等待辦理,但是有的客戶持有的是金卡,則應該被有限辦理。優先隊列則用於處理這類的問題。
即優先隊:數據的存入是按照先進先出的方式放進去的,但是存入的數據有對應的優先級,則取出的時候根據優先級取出。
三:用棧實現走迷宮
老鼠走迷宮是棧的一個典型應用,如下,有一個簡單的迷宮(m代表入口,e代表出口,0代表該路行得通,1代表牆):
1 1 0 0
0 0 0 e
0 0 m 1
思想:老鼠會嘗試所有可行的路徑(上、下、左、右四個方向),如果碰到了死角,則會返回到最後一步再嘗試其他路徑,所以上下左右方向的順序會影響到最後尋找的出路。
實現:
我們將迷宮放在一個二維數組裏,由於數組的計數從0開始,我們爲了更直觀,在初始二維數組周圍加上2,如下
1 1 1 1 1 1
1 1 1 0 0 1
1 0 0 0 e 1
1 0 0 m 1 1
1 1 1 1 1 1
這裏需要用到棧,將可能走的位置按照一定的規律壓入棧中(例如上下左右),例如到了A的位置,則在A的基礎上往下走,如果A後面沒有可行的路徑,則返回至A的上一步。下面詳解實現。
(1)構建MazeCell:表示迷宮的位置
public class MazeCell {
int x;
int y;
public MazeCell(){
}
public MazeCell(int a,int b){
this.x = a;
this.y = b;
}
public Booleanequals(MazeCell cell){
if(cell.x == this.x&&cell.y==this.y)
return true;
else
return false;
}
}
(2)尋找出路的具體實現
public class Maze {
//構建maze所需的參數
char[][] maze = new char[5][6];
char entrance = 'm';
char exit = 'e';
char pass= '0';
char notPass='1';
char visited = '2';
//獲得maze路徑所需參數
Stack<MazeCell> pushUnvisited = new Stack<MazeCell>();
MazeCell currentCell = new MazeCell();
MazeCell exitCell = new MazeCell(2,4);
MazeCell entryCell = new MazeCell(3,3);
public static void main(String[]args){
Maze maze = new Maze();
maze.makeMaze();
maze.getPath();
}
//構造一個maze
public void makeMaze(){
//給迷宮外加上1
for(int i = 0;i<6;i++){
maze[0][i] =notPass;
maze[4][i]=notPass;
}
for(int j = 0;j<5;j++){
maze[j][0] =notPass;
maze[j][5]=notPass;
}
maze[1][1] = notPass;
maze[1][2] =notPass;
maze[1][3] = pass;
maze[1][4] = pass;
maze[2][1] = pass;
maze[2][2] =pass;
maze[2][3] = pass;
maze[2][4] =exit;
maze[3][1] = pass;
maze[3][2] =pass;
maze[3][3] = entrance;
maze[3][4] =notPass;
}
//尋找走出迷宮的路徑
public void getPath(){
currentCell = entryCell;
while(!currentCell.equals(exitCell)){
int x = currentCell.x;
int y = currentCell.y;
//搜索路徑爲上下左右,不同的順序會有不同結果
pushStack(x-1,y);
pushStack(x+1,y);
pushStack(x,y-1);
pushStack(x,y+1);
//把走過的位置標記成visited
if(!currentCell.equals(entryCell)){
maze[x][y] = visited;
}
//如果在還沒到達終點,棧就空了,說明該迷宮米有出路
if(pushUnvisited.isEmpty()){
System.out.println("failure");
return;
}
//將當前位置往前移
MazeCell tmp = pushUnvisited.pop();
currentCell = tmp;
//輸出我走過的節點
System.out.println(tmp.x+","+tmp.y);
}
}
public void pushStack(int x ,int y){
//如果是visited或notPass,則不能壓進棧
if(maze[x][y] == pass||maze[x][y]==exit){
pushUnvisited.push(new MazeCell(x,y));
}
}
}