# 堆疊Stack
## 1. 簡介
Stack (堆疊) 是一種遵循 **後進先出 (LIFO, Last In First Out)** 的資料結構
## 2. Stack 的基本概念
### 2.1 定義
**Stack** 是一種只允許在一端進行插入和刪除操作的資料結構,具有以下操作:
- **Push**:將元素存入堆疊頂部。
- **Pop**:從堆疊頂部移除元素。
- **Peek**:取得堆疊頂部元素但不移除。
- **Empty**:判斷堆疊是否為空。
- **Full** : 判斷堆疊是否滿。
### 2.2 Stack 的特點
- **LIFO (Last In First Out)**:最後進入的元素最先被移除。
- 操作時間複雜度:Push 和 Pop 操作皆為 $O(1)$。
## 3. Stack 的實作
### 3.1 使用陣列實作
```c
#include <stdio.h>
#include <stdlib.h>
#define MAX 1000
// Function to check if the stack is empty
int isEmpty(int top) {
return top == -1;
}
// Function to check if the stack is full
int isFull(int top) {
return top == MAX - 1;
}
// Function to push an element onto the stack
void push(int stack[], int *top, int value) {
if (isFull(*top)) {
printf("Stack overflow\n");
return;
}
stack[++(*top)] = value;
}
// Function to pop an element from the stack
int pop(int stack[], int *top) {
if (isEmpty(*top)) {
printf("Stack underflow\n");
return -1; // Return -1 to indicate an error
}
return stack[(*top)--];
}
// Function to get the top element of the stack
int peek(int stack[], int top) {
if (isEmpty(top)) {
printf("Stack is empty\n");
return -1; // Return -1 to indicate an error
}
return stack[top];
}
int main(int argc, char *argv[]) {
int stack[MAX];
int top = -1;
int choice, value;
do {
printf("1. Push\n");
printf("2. Pop\n");
printf("3. Peek\n");
printf("4. Check if empty\n");
printf("5. Check if full\n");
printf("6. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Enter value to push: ");
scanf("%d", &value);
push(stack, &top, value);
break;
case 2:
value = pop(stack, &top);
if (value != -1) {
printf("Popped value: %d\n", value);
}
break;
case 3:
value = peek(stack, top);
if (value != -1) {
printf("Top value: %d\n", value);
}
break;
case 4:
if (isEmpty(top)) {
printf("Stack is empty\n");
} else {
printf("Stack is not empty\n");
}
break;
case 5:
if (isFull(top)) {
printf("Stack is full\n");
} else {
printf("Stack is not full\n");
}
break;
case 6:
printf("Exiting...\n");
break;
default:
printf("Invalid choice\n");
}
} while (choice != 6);
printf("Final stack contents: ");
for (int i = 0; i <= top; i++) {
printf("%d ", stack[i]);
}
printf("\n");
return 0;
}
```
### 3.2 使用鏈結串列實作
```c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct Node {
int data;
struct Node *next;
} Node;
typedef struct {
Node *top;
} Stack;
void init(Stack *s) {
s->top = NULL;
}
bool isEmpty(Stack *s) {
return s->top == NULL;
}
void push(Stack *s, int value) {
Node *newNode = (Node *)malloc(sizeof(Node));
if (!newNode) {
printf("Memory allocation failed\n");
return;
}
newNode->data = value;
newNode->next = s->top;
s->top = newNode;
}
void pop(Stack *s) {
if (isEmpty(s)) {
printf("Stack underflow\n");
return;
}
Node *temp = s->top;
s->top = s->top->next;
free(temp);
}
int peek(Stack *s) {
if (isEmpty(s)) {
printf("Stack is empty\n");
return -1;
}
return s->top->data;
}
void display(Stack *s) {
Node *current = s->top;
while (current) {
printf("%d ", current->data);
current = current->next;
}
printf("\n");
}
int main() {
Stack s;
init(&s);
push(&s, 10);
push(&s, 20);
display(&s);
pop(&s);
printf("Top element: %d\n", peek(&s));
return 0;
}
```
## 4. Stack 的應用
### 4.1中序轉後序
將運算式從左往右掃描
- 運算子放入到**stack**
若stack中的運算子優先權較大或是相等的則要pop運算子
``(``可以被任何運算子壓
當遇到``)``則要pop運算子到``(``
使他們互相抵消。
## 5. Stack 的優缺點
### 5.1 優點
- 操作簡單,**Push** 和 **Pop** 時間複雜度為 $O(1)$。
- 可用於解決多種經典問題,如括號匹配與 **DFS**。
### 5.2 缺點
- 陣列實作的堆疊大小固定,可能浪費記憶體或發生溢出。
- 鏈結串列實作演算法較複雜。