栈,后进先出(LIFO)
只允许在一端(栈顶)进行入栈和出栈的操作,另一端为栈底
使用顺序表实现
顺序栈的操作实现
#pragma once
#include<stdio.h>
#include<assert.h>
#include<windows.h>
#include<Windows.h>
typedef struct Position{
int x;
int y;
}Postion;//迷宫位置
//typedef Position SDataType;
typedef int SDataType;
#define MAX_SIZE (100)
typedef struct Stack{
SDataType arr[MAX_SIZE];//size
int top;//表示有效数据个数;表示当前可用位置
}Stack;
//初始化
void StackInit(Stack *pS);
//入栈
void StackPush(Stack *pS, SDataType data);
//出栈
void StackPop(Stack *pS);
//返回栈顶元素
SDataType StackTop(Stack *pS);
//判断是否为空,1表示空,0表示非空
int StackIsEmpty(Stack *pS);
//返回栈元素个数
int StackSize(Stack *pS);
//栈拷贝
void StackCopy(Stack *pDest, Stack *pSrc);
#include "Stack.h"
//初始化
void StackInit(Stack *pS)
{
assert(pS);
pS->top = 0;
}
//入栈
void StackPush(Stack *pS, SDataType data)
{
assert(pS);
assert(pS->top < MAX_SIZE);
pS->arr[pS->top++] = data;
}
//出栈
void StackPop(Stack *pS)
{
assert(pS);
assert(pS->top > 0);
pS->top--;
}
//返回栈顶元素
SDataType StackTop(Stack *pS)
{
assert(pS);
assert(pS->top > 0);
return pS->arr[pS->top - 1];
}
//判断是否为空,1表示空,0表示非空
int StackIsEmpty(Stack *pS)
{
return pS->top == 0 ? 1 : 0;
}
//返回栈元素个数
int StackSize(Stack *pS)
{
return pS->top;
}
//栈拷贝
void StackCopy(Stack *pDest, Stack *pSrc)
{
pDest->top = pSrc->top;
memcpy(pDest->arr, pSrc->arr, sizeof(SDataType)*pSrc->top);
}
void print(Stack *pS)
{
for (int i = 0; i < pS->top; i++){
printf("%d ", pS->arr[i]);
}
printf("\n");
}
int main()
{
Stack stack;
StackInit(&stack);
StackPush(&stack, 1);
StackPush(&stack, 2);
StackPush(&stack, 3);
StackPush(&stack, 4);
print(&stack);
StackPop(&stack);
StackPop(&stack);
print(&stack);
printf("%d\n", StackTop(&stack));
Stack stack1;
StackInit(&stack1);
StackCopy(&stack1, &stack);
print(&stack1);
system("pause");
return 0;
}
应用1:
使用顺序栈实现检测括号匹配问题
#include "Stack.h"
//括号是否匹配
void IsBracketMatch(const char *str)
{
const char *str1 = str;
Stack stack;
char ch;
StackInit(&stack);
while (*str1){
switch (*str1){
case '(':
case '{':
case '[':
StackPush(&stack, *str1);
break;
case ')':
case '}':
case ']':
if (StackIsEmpty(&stack)){//1为空
printf("右括号比左括号多\n");
return;
}
ch = StackTop(&stack);
StackPop(&stack);
if (!((ch == '(' && *str1 == ')') || (ch == '{' && *str1 == '}') || \
(ch == '[' && *str1 == ']'))){
printf("左右括号不匹配\n");
return;
}
break;
}
str1++;
}
if (!StackIsEmpty(&stack)){
printf("左括号比右括号多\n");
return;
}
printf("左右括号匹配\n");
}
int main()
{
IsBracketMatch("(())abc{[(])}");
IsBracketMatch("(()))abc{[]}");
IsBracketMatch("(()()abc{[]}");
IsBracketMatch("(())abc{[]()}");
system("pause");
return 0;
}
应用2:
走出迷宫
#include "Stack.h"
//使用栈与递归实现迷宫
#define ROWS 6
#define COLS 6
//判断是否可走
int IsAccess(int maze[ROWS][COLS], Position pos)
{
if (pos.y < 0 || pos.y >= ROWS) {
return 0;
}
if (pos.x < 0 || pos.x >= COLS) {
return 0;
}
return maze[pos.y][pos.x] == 1 ? 1 : 0;
}
//是否找到出口
int IsExit(Position pos)
{
return pos.x == COLS - 1 ? 1 : 0;
}
void PrintMaze(int maze[ROWS][COLS])
{
int i, j;
for (i = 0; i < ROWS; i++) {
for (j = 0; j < COLS; j++) {
printf("%d ", maze[i][j]);
}
printf("\n");
}
}
void GoMaze(int maze[ROWS][COLS], Position entry)
{
Position pos = entry; // 当前所处位置
Position nextPos; // 要尝试的位置
Stack stack;
StackInit(&stack);
while (1) {
maze[pos.y][pos.x] = 2; // 表示这个路来过
system("cls");
PrintMaze(maze);
Sleep(500);
if (IsExit(pos)) {
// 回溯
pos = StackTop(&stack);
StackPop(&stack);
maze[pos.y][pos.x] = 3;
system("cls");
printf("出口\n");
PrintMaze(maze);
Sleep(2000);
continue;
}
// 左 -> 上 -> 右 -> 下
nextPos = pos;
nextPos.x -= 1;
if (IsAccess(maze, nextPos)) {
StackPush(&stack, pos);
pos = nextPos;
continue;
}
nextPos = pos;
nextPos.y -= 1;
if (IsAccess(maze, nextPos)) {
StackPush(&stack, pos);
pos = nextPos;
continue;
}
nextPos = pos;
nextPos.x += 1;
if (IsAccess(maze, nextPos)) {
StackPush(&stack, pos);
pos = nextPos;
continue;
}
nextPos = pos;
nextPos.y += 1;
if (IsAccess(maze, nextPos)) {
StackPush(&stack, pos);
pos = nextPos;
continue;
}
// 回溯
if (StackIsEmpty(&stack)) {
printf("迷宫探索结束\n");
return;
}
pos = StackTop(&stack);
StackPop(&stack);
}
}
int main()
{
int maze[ROWS][COLS] = {
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 1, 1, 1 },
{ 0, 0, 1, 0, 1, 0 },
{ 0, 0, 1, 1, 1, 0 },
{ 0, 0, 1, 0, 1, 1 },
{ 0, 0, 1, 0, 0, 0 }
};
Position entry = { 2, 5 };
GoMaze(maze, entry);
PrintMaze(maze);
system("pause");
return 0;
}
找出走出迷宫最短路径
#include "Stack.h"
//使用栈与递归实现迷宫
#define ROWS 6
#define COLS 6
//判断是否可走
int IsAccess(int maze[ROWS][COLS], Position pos)
{
if (pos.y < 0 || pos.y >= ROWS) {
return 0;
}
if (pos.x < 0 || pos.x >= COLS) {
return 0;
}
return maze[pos.y][pos.x] == 1 ? 1 : 0;
}
//是否找到出口
int IsExit(Position pos)
{
return (pos.x == COLS - 1) ? 1 : 0;
}
void PrintMaze(int maze[ROWS][COLS])
{
int i, j;
for (i = 0; i < ROWS; i++) {
for (j = 0; j < COLS; j++) {
printf("%d ", maze[i][j]);
}
printf("\n");
}
}
void GoMazeRecursion(Stack *pPath, Stack *pShort, int maze[][COLS], Position pos)
{//1代表路,0代表墙
maze[pos.y][pos.x] = 2; //表示这个路来过
StackPush(pPath, pos);
Position nextPos;
if (IsExit(pos)){
if (StackIsEmpty(pShort) || StackSize(pPath) < StackSize(pShort)){
//找到新的最短路径
StackCopy(pShort, pPath);
}
maze[pos.y][pos.x] = 1;
StackPop(pPath);
return;
}
nextPos = pos;// 左 -> 上 -> 右 -> 下
nextPos.x -= 1;
if (IsAccess(maze, nextPos)) {
GoMazeRecursion(pPath, pShort, maze, nextPos);
}
nextPos = pos;
nextPos.y -= 1;
if (IsAccess(maze, nextPos)) {
GoMazeRecursion(pPath, pShort, maze, nextPos);
}
nextPos = pos;
nextPos.x += 1;
if (IsAccess(maze, nextPos)) {
GoMazeRecursion(pPath, pShort, maze, nextPos);
}
nextPos = pos;
nextPos.y += 1;
if (IsAccess(maze, nextPos)) {
GoMazeRecursion(pPath, pShort, maze, nextPos);
}
StackPop(pPath);
maze[pos.y][pos.x] = 1;
}
int main()
{
Stack pathStack;
Stack shortPathStack;
int maze[ROWS][COLS] = {
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 1, 1, 1 },
{ 0, 0, 1, 0, 1, 0 },
{ 0, 0, 1, 1, 1, 0 },
{ 0, 0, 1, 0, 1, 1 },
{ 0, 0, 1, 0, 0, 0 }
};
Position entry = { 2, 5 };
StackInit(&pathStack);
StackInit(&shortPathStack);
GoMazeRecursion(&pathStack, &shortPathStack, maze, entry);
while (!StackIsEmpty(&shortPathStack)){
Position pos = StackTop(&shortPathStack);
StackPop(&shortPathStack);
maze[pos.y][pos.x] = 4;
}
PrintMaze(maze);
system("pause");
return 0;
}