棧和隊列的底層實現及迷宮問題

一:棧

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));
        }
     }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章