1. 程式人生 > >資料結構-棧和棧的應用

資料結構-棧和棧的應用

  • 棧的定義

        棧是一種特殊的線性表。其特殊性在於限定插入和刪除資料元素的操作只能在線性表的一端進行。它按照後進先出的原則儲存資料,先進入的資料被壓入棧底,最後的資料在棧頂,需要讀資料的時候從棧頂開始彈出資料(最後一個數據被第一個讀出來)。棧具有記憶作用,對棧的插入與刪除操作中,不需要改變棧底指標。

       棧分順序棧和鏈式棧,不過通常使用的是順序棧。下面介紹順序棧。

  • 棧的儲存方式

typedef struct Stack
{
	SDataType array[MAX_SIZE];
	int top;		
} Stack;
  • 棧的基本運算

#pragma once

#include <assert.h>

#define MAX_SIZE (100)

typedef int SDataType;

typedef struct Stack
{
	SDataType array[MAX_SIZE];
	int top;		
} Stack;

//初始化
void StackInit(Stack *pS)
{
	pS->top = 0;
}

//銷燬
void StackDestroy(Stack *pS)
{
	pS->top = 0;
}

//壓棧
void StackPush(Stack *pS, SDataType data)
{
	assert(pS->top < MAX_SIZE);
	pS->array[pS->top++] = data;
}

//出棧
void StackPop(Stack *pS)
{
	assert(pS->top > 0);
	pS->top--;
}

//返回棧頂元素
SDataType StackTop(const Stack *pS)
{
	assert(pS->top > 0);
	return pS->array[pS->top - 1];
}

//站內元素的個數
int StackSize(const Stack *pS)
{
	return pS->top;
}

//判斷棧是否為空
int StackEmpty(const Stack *pS)
{
	return pS->top == 0 ? 1 : 0;
}

棧的應用

  • 括號匹配問題

#define _CRT_SECURE_NO_DEPRECATE 1

#include "stack.h"

void MatchBrackets(const char* p)
{
	Stack stack;
	StackInit(&stack);

	while (*p!='\0')
	{
		switch (*p)
		{
		case '(':
		case '{':
		case '[':
			StackPush(&stack,*p);
			break;
		case ')':
		case '}':
		case ']':
			if (StackEmpty(&stack))
			{
				printf("右括號多\n");
				return;
			}
			char top = StackTop(&stack);
			StackPop(&stack);

			if (!((top == '(' && *p == ')') ||
				(top == '[' && *p == ']' )||
				(top == '{' && *p == '}' )))
			{
				printf("左右括號不匹配\n");
				return;
			}
			break;
		default:
			break;
		}
		p++;
	}
	if (!StackEmpty(&stack))
	{
		printf("左括號多\n");
	}
	else
	{
		printf("左右括號匹配\n");
	}
}


int main()
{
	char a[] = "(())abc{[(])}"; // 左右括號次序匹配不正確
	char b[] = "(()))abc{[]}"; // 右括號多於左括號
	char c[] = "(()()abc{[]}"; // 左括號多於右括號
	char d[] = "(())abc{[]()}";

	MatchBrackets(a);
	MatchBrackets(b);
	MatchBrackets(c);
	MatchBrackets(d);
	return 0;
}
  • 逆波蘭表示式


#include "stack.h"

typedef enum 
{
	NUMBER,
	OPERATE
}Type;


typedef enum 
{
	ADD,
	SUB,
	DIV,
	MUL,
	NOUSED
}OP;


typedef struct 
{
	Type type;
	int number;
	OP operate;
}Item;


Item array[] = 
{
	{
		NUMBER,
		125,
		NOUSED
	},
	{
		NUMBER,
		145,
		NOUSED
	},
	{
		OPERATE,
		-1,
		SUB
	}
};


void RPN(Item array[], int size)
{
	Stack stack;
	StackInit(&stack);

	for (int i = 0; i < size; i++)
	{
		if (array[i].type == NUMBER)
		{
			StackPush(&stack, array[i].number);
		}
		else
		{
			int n1 = StackTop(&stack);
			StackPop(&stack);
			int n2 = StackTop(&stack);
			StackPop(&stack);
			int result;

			switch (array[i].operate)
			{
			case ADD:
				result = n1 + n2;
				break;
			case SUB:
				result = n2 - n1;
				break;
			case MUL:
				result = n1 * n2;
				break;
			case DIV:
				result = n2 / n1;
				break;
			}
			StackPush(&stack, result);
		}
	}

	assert(StackSize(&stack) == 1);

	printf("%d\n", StackTop(&stack));
}

int main()
{
	int size = sizeof(array) / sizeof(array[0]);
	RPN(array, size); 
		return 0;	
}
	
  • 迷宮

  • 簡單迷宮
#define _CRT_SECURE_NO_DEPRECATE 1

#include "Windows.h"
#include "stdio.h"

typedef struct
{
	int x;
	int y;
}position;

#include "stack.h"

#define ROWS (6)
#define COLS (6)

int g_maze[ROWS][COLS] = {
	{ 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 1, 0, 0, 0 },
	{ 0, 0, 1, 0, 0, 0 },
	{ 0, 0, 1, 1, 1, 0 },
	{ 0, 0, 1, 0, 1, 1 },
	{ 0, 0, 1, 0, 0, 0 }
};



void PrintMaze()
{
	for (int i = 0; i < ROWS; i++)
	{
		for (int j = 0; j < COLS; j++)
		{
			if (g_maze[i][j]==1)
			{
				printf("  ");
			}
			else if (g_maze[i][j]==0)
			{
				printf("■");
			}
			else if (g_maze[i][j] == 2) {
				printf("⊙");
			}
			else
			{
				printf("  ");
			}
		}
		printf("\n");
	}
}


int IsExit(position pos)
{
	if (pos.y==COLS-1)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}



int CanPass(position pos)
{
	// 先判斷是否越界
	if (pos.x < 0 || pos.x >= ROWS) {
		return 0;
	}

	if (pos.y < 0 || pos.y >= COLS) {
		return 0;
	}

	// 再判斷是否是路
	if (g_maze[pos.x][pos.y] == 1) 
	{
		return 1;
	}
	else {
		return 0;
	}
}

void GoMaze(position entry)
{
	Stack stack;

	StackInit(&stack);
	position pos = entry;
	position nextpos;

	while (1)
	{
		g_maze[pos.x][pos.y] = 2;//走過的路標記為2

		system("cls");
		PrintMaze();
		Sleep(300);

		StackPush(&stack, pos);

		if (IsExit(pos))
		{
			printf("找到出口\n");
			return;
		}


		nextpos = pos;
		nextpos.y--;
		if (CanPass(nextpos))
		{
			pos = nextpos;
			continue;
		}

		nextpos = pos;
		nextpos.x -= 1;
		if (CanPass(nextpos)) {
			pos = nextpos;
			continue;
		}

		nextpos = pos;
		nextpos.y += 1;
		if (CanPass(nextpos)) {
			pos = nextpos;
			continue;
		}

		nextpos = pos;
		nextpos.x += 1;
		if (CanPass(nextpos)) {
			pos = nextpos;
			continue;
		}

		
		g_maze[pos.x][pos.y] = 3;
		pos = StackTop(&stack);
		StackPop(&stack);
		if (StackEmpty(&stack))
		{
			printf("結束\n");
			return;
		}
		pos = StackTop(&stack);
		StackPop(&stack);
	}

}


int  main()
{
	position entry = { 5, 2 };
	GoMaze(entry);
	return 0;
}


  • 多通路迷宮:通路間不帶環
#define _CRT_SECURE_NO_DEPRECATE 1

#include "Windows.h"
#include "stdio.h"

typedef struct  
{
	int x;
	int y;
} position;

#define ROWS (6)
#define COLS (6)

#include "stack.h"

int g_maze[ROWS][COLS] = {
	{ 0, 0, 0, 0, 0, 0 },
	{ 0, 1, 1, 1, 1, 1 },
	{ 0, 1, 0, 0, 0, 0 },
	{ 0, 1, 0, 0, 0, 0 },
	{ 0, 1, 1, 1, 1, 1 },
	{ 0, 1, 0, 0, 0, 0 }
};

void PrintMaze()
{
	for (int i = 0; i < ROWS; i++)
	{
		for (int j = 0; j < COLS; j++)
		{
			if (g_maze[i][j] == 1)
			{
				printf("  ");
			}
			else if (g_maze[i][j] == 0)
			{
				printf("■");
			}
			else if (g_maze[i][j] == 2) {
				printf("⊙");
			}
			else
			{
				printf("  ");
			}
		}
		printf("\n");
	}
}


int IsExit(position pos)
{
	if (pos.y == COLS-1)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}


int CanPass(position pos)
{
	// 先判斷是否越界
	if (pos.x < 0 || pos.x >= ROWS) {
		return 0;
	}

	if (pos.y < 0 || pos.y >= COLS) {
		return 0;
	}

	// 再判斷是否是路
	if (g_maze[pos.x][pos.y] == 1) {
		return 1;
	}
	else {
		return 0;
	}
}


void GoMaze(position entry)
{
	Stack stack;
	StackInit(&stack);

	position pos = entry;
	position nextpos;

	while (1)
	{
		g_maze[pos.x][pos.y] = 2;
		
		system("cls");
		PrintMaze();
		Sleep(100);

		StackPush(&stack, pos);

		if (IsExit(pos))
		{
			printf("找到出口\n");
			g_maze[pos.x][pos.y] = 0;
			goto BACK;
		}
		

		nextpos = pos;
		nextpos.y--;
		if (CanPass(nextpos))
		{
			pos = nextpos;
	
			continue;
		}

		nextpos = pos;
		nextpos.x -= 1;
		if (CanPass(nextpos)) 
		{
			pos = nextpos;
			continue;
		}

		nextpos = pos;
		nextpos.y += 1;
		if (CanPass(nextpos)) 
		{
			pos = nextpos;
			continue;
		}

		nextpos = pos;
		nextpos.x += 1;
		if (CanPass(nextpos)) 
		{
			pos = nextpos;
			continue;
		}
		
BACK:
		pos = StackTop(&stack);
		StackPop(&stack);
		if (StackEmpty(&stack))
		{
			printf("結束\n");
			return;
		}
		pos = StackTop(&stack);
		StackPop(&stack);
	}
}



int main()
{
	position entry = { 5, 1 };
	GoMaze(entry);
	return 0;
}

  • 多通路迷宮:通路帶環
#define _CRT_SECURE_NO_DEPRECATE 1

#include "Windows.h"
#include "stdio.h"

typedef struct
{
	int x;
	int y;
} position;

#define ROWS (6)
#define COLS (6)

#include "stack.h"

int g_maze[ROWS][COLS] = {
	{ 0, 0, 0, 0, 0, 0 },
	{ 0, 1, 1, 1, 0, 0 },
	{ 0, 1, 0, 1, 0, 0 },
	{ 0, 1, 0, 1, 0, 0 },
	{ 0, 1, 1, 1, 1, 1 },
	{ 0, 1, 0, 0, 0, 0 }
};


void PrintMaze()
{
	for (int i = 0; i < ROWS; i++)
	{
		for (int j = 0; j < COLS; j++)
		{
			if (g_maze[i][j] == 1)
			{
				printf("  ");
			}
			else if (g_maze[i][j] == 0)
			{
				printf("■");
			}
			else if (g_maze[i][j] == 2) {
				printf("⊙");
			}
			else
			{
				printf("  ");
			}
		}
		printf("\n");
	}
}


int IsExit(position pos)
{
	if (pos.y == COLS - 1)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}


int CanPass(position pos)
{
	// 先判斷是否越界
	if (pos.x < 0 || pos.x >= ROWS) {
		return 0;
	}

	if (pos.y < 0 || pos.y >= COLS) {
		return 0;
	}

	// 再判斷是否是路
	if (g_maze[pos.x][pos.y] == 1) {
		return 1;
	}
	else {
		return 0;
	}
}


void GoMazeR(position pos)
{
	
	position nextpos;
	g_maze[pos.x][pos.y] = 2;
	
	system("cls");
	PrintMaze();
	Sleep(300);
	
	if (IsExit(pos))
	{
		printf("找到出口\n");
		g_maze[pos.x][pos.y] = 1;
		return;
	}
	
	nextpos = pos;
	nextpos.y-=1;
	if (CanPass(nextpos))
	{
		GoMazeR(nextpos);
	}

	nextpos = pos;
	nextpos.x -= 1;

	if (CanPass(nextpos))
	{
		GoMazeR(nextpos);
	}

	nextpos = pos;
	nextpos.y += 1;
	if (CanPass(nextpos))
	{
		GoMazeR(nextpos);
	}

	nextpos = pos;
	nextpos.x += 1;
	if (CanPass(nextpos))
	{
		GoMazeR(nextpos);
	}

	g_maze[pos.x][pos.y] = 1;
}



int main()
{
	position entry = { 5, 1 };
	GoMazeR(entry);
	return 0;
}