C++ STL stack介紹與使用方法
阿新 • • 發佈:2019-01-10
stack(棧)
在學習資料結構中我們知道,棧是一種邏輯資料結構,其具有後進先出的特性。同時,我們也可以把它想象成一個容器,一個真實容器,新增與刪除只能在容器頂部完成。棧的應用非常廣,我們知道任何程式從記憶體進入CPU執行,系統為了保證程式正確的執行,將程式二進位制程式碼存放在一個系統執行棧上面。呼叫函式A,則A的程式碼入棧,函式A中呼叫了函式B,則B入棧,B執行結束後,先出棧,這時再繼續執行函式A。因此這種後進先出的工作方式在很多地方都非常有用。
stack內部資料結構可以是其它容器,因此可以看成是容器的容器。stack內部實現預設使用雙端佇列(deque)來實現,當然你也可以主動指定儲存內省,如vector與list
標頭檔案: #include
建構函式
deque<int> mydeque(3, 100);
vector<int> myvector(2, 200);
stack<int> first; //申明一個棧物件
stack<int> second(mydeque); //用一個雙端佇列初始化一個棧物件,預設內部容器為deque
stack<int, vector<int> > third; //表明third物件內部資料結構為vector
stack<int, vector<int > > fourth(myvector); //用vector初始化fourth物件,必須要主動指定內部容器型別
常用函式
- 由於stack是一種操作受限制的線性結構,所有的操作只能是在棧頂,因此其內部函式也比較少。
deque<int> mydeque(3, 100);
stack<int> first(mydeque);
first.empty(); //判斷是否為空
int size = first.size(); //返回棧內元素個數
int n;
n = first.top(); //返回棧頂元素
first.pop(); //彈出棧頂元素
first.push(20); //向棧內新增元素
棧的應用
- 棧的應用非常廣,常見的的圖深度優先搜尋、表示式求職、走迷宮的,下面是利用棧來完成走迷宮的原始碼。
//走迷宮求解
#include <iostream>
#include <stack>
using namespace std;
class Position
{
public:
int row; //行
int col; //列
int dir; //預設為0。 1~4:該點到下一點的方向,分別為右上左下
};
//迷宮大小
#define MAZE_ROWS 3
#define MAZE_COLS 4
//在迷宮外部加一堵牆
#define NEW_MAZE_ROWS (MAZE_ROWS + 2)
#define NEW_MAZE_COLS (MAZE_COLS + 2)
//起點
#define ENTER_ROW 1
#define ENTER_COL 1
//終點
#define EXIT_ROW 3
#define EXIT_COL 4
//儲存路徑的棧
stack<Position> mazeStack;
//迷宮地圖
int maze[NEW_MAZE_ROWS][NEW_MAZE_COLS]
= {
1, 1, 1, 1, 1, 1,
1, 0, 1, 0, 0, 1,
1, 0, 0, 0, 1, 1,
1, 0, 1, 0, 0, 1,
1, 1, 1, 1, 1, 1
};
//記錄地圖上的某個位置是否已經被訪問過,為1表示訪問過
int mazeFlag[NEW_MAZE_ROWS][NEW_MAZE_COLS];
//判斷某個點是否被訪問過以及是否可通過
bool pass(Position pos)
{
if (maze[pos.row][pos.col] == 0 &&
mazeFlag[pos.row][pos.col] == 0)
{
return true;
}
return false;
}
//當前點cur的下一個點pos,同時更新當前點到下一個點的方向
//按照上、右、下、左的順序依次獲取當前點的下一個點
bool next_position(Position & cur, Position & nextpos)
{
nextpos = cur;
nextpos.dir = 0;
//根據當前點到下一個點的方向(目前的方向)
//來確定下一個點的方向,如果當前點到下一個點的方向已經是4(左)
//則表明當前點沒有路徑,不應該選擇
switch (cur.dir)
{
case 0:
nextpos.row -= 1;
cur.dir = 1;
break;
case 1:
nextpos.col += 1;
cur.dir = 2;
break;
case 2:
nextpos.row += 1;
cur.dir = 3;
break;
case 3:
nextpos.col -= 1;
cur.dir = 4;
break;
case 4:
cur.dir = -1;
return false;
break;
case -1:
return false;
break;
}
return true;
}
//判斷是否
int maze_solution()
{
//起點座標為(1, 1)
Position pos;
pos.row = 1;
pos.col = 1;
pos.dir = 0;
mazeStack.push(pos); //起點如棧
int totalSteps = 0; //總共走的步數
while (!mazeStack.empty()) //只要棧不為空,則繼續尋找
{
Position curPos = mazeStack.top();
Position nextPos;
//尋找下一個可達的點,同時更新當前位置的方向
if (next_position(curPos, nextPos))
{
//更新當前位置方向
mazeStack.pop();
mazeStack.push(curPos);
if (pass(nextPos))
{
mazeFlag[curPos.row][curPos.col] = 1; //入棧之前標記為已訪問
mazeStack.push(nextPos);
totalSteps++;
if (nextPos.row == EXIT_ROW && nextPos.col == EXIT_COL)
{
//成功找到出口,返回
return totalSteps;
}
}
}
else
{
mazeStack.pop();
totalSteps--;
}
}
return totalSteps;
}
int main()
{
memset(mazeFlag, 0, sizeof(mazeFlag));
stack<Position> tmpStack;
int steps = maze_solution();
if (steps > 0)
{
while (!mazeStack.empty())
{
tmpStack.push(mazeStack.top());
mazeStack.pop();
}
cout << "the total steps: " << steps << endl;
while (!tmpStack.empty())
{
cout << tmpStack.top().row << " " << tmpStack.top().col << endl;
tmpStack.pop();
}
}
else
{
cout << "can not find the path.." << endl;
}
return 0;
}