#### 鏈式棧實現
##### linkstack.h
#ifndef _LINKSTACK_H
#define _LINKSTACK_H
// 引入相關的庫文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定義元素類型的別名
typedef int DATA;
//定義鏈式棧節點
typedef struct node
{
?? ?DATA data;
?? ?struct node *next;
}NODE;
//定義鏈式棧結構體
typedef struct?
{
?? ?NODE *top; ? ? //棧頂指針,其實就是鏈表中的頭節點
?? ?int size; ? ? //當前元素數量
?? ?int capacity; ? ? //棧容量
}LinkStack;
/**
?* 初始化鏈式棧
?* @param s 棧結構體指針(需由調用者提前分配內存)
?* @param num 棧容量的大小
?* @return 初始化成功返回0,否則返回-1
?*/
extern int lstack_init(LinkStack *s, int num);
/**
?* 判斷棧是否已滿
?* @param s 棧結構體指針(需由調用者提前分配內存)
?* @return 棧已滿返回1
?*/
extern int lstack_isfull(LinkStack *s);
/**
?* 入棧
?* @param s 棧結構體指針(需由調用者提前分配內存)
?* @param data 待入棧的數據
?* @return 成功返回0,否則返回-1
?*/
extern int lstack_push(LinkStack *s, DATA data);
/**
?* 判斷棧是否為空
?* @param s 棧結構體指針(需由調用者提前分配內存)
?* @return 棧為空返回1
?*/
extern int lstack_isempty(LinkStack *s);
/**
?* 出棧
?* @param s 棧結構體指針(需由調用者提前分配內存)
?* @param data 接收出棧的數據指針
?* @return 成功返回0,否則返回-1
?*/
extern int lstack_pop(LinkStack *s, DATA *data);
/**
?* 銷毀棧
?*/
extern void lstack_destroy(LinkStack *s);
#endif //_LINKSTACK_H
```
##### linkstack.c
#include "linkstack.h"
/**
?* 初始化鏈式棧
?* @param s 棧結構體指針(需由調用者提前分配內存)
?* @param num 棧容量的大小
?* @return 初始化成功返回0,否則返回-1
?*/
int lstack_init(LinkStack *s, int num)
{
?? ?//空指針檢查
?? ?if(!s)
?? ?{
?? ??? ?perror("創建失敗!");
?? ??? ?return -1;
?? ?}
?? ?
?? ?//num的檢查
?? ?if(num <= 0)
?? ?{
?? ??? ?perror("容量有誤,創建失敗!");
?? ??? ?return -1;
?? ?}
?? ?
?? ?//初始化棧屬性
?? ?s->top = NULL; ? ? //棧頂指針置空,表示空棧
?? ?s->size = 0; ? ? //當前元素數量為0?
?? ?s->capacity = num; ? ? //設置容量限制(需后續操作中校驗)
?? ?
?? ?return 0;
}
/**
?* 判斷棧是否已滿
?* @param s 棧結構體指針(需由調用者提前分配內存)
?* @return 棧已滿返回1
?*/
int lstack_isfull(LinkStack *s)
{
?? ?return s->size >= s->capacity;
}
/**
?* 入棧
?* @param s 棧結構體指針(需由調用者提前分配內存)
?* @param data 待入棧的數據
?* @return 成功返回0,否則返回-1
?*/
int lstack_push(LinkStack *s, DATA data)
{
?? ?//判斷棧是否已滿
?? ?if(lstack_isfull(s))
?? ?{
?? ??? ?perror("棧已滿,數據無法入棧!");
?? ??? ?return -1;
?? ?}
?? ?
?? ?//創建新節點
?? ?NODE *p = (NODE*)malloc(sizeof(NODE));
?? ?if(!p)
?? ?{
?? ??? ?perror("Memory allocation failed!");
?? ??? ?return -1;
?? ?}
?? ?
?? ?//初始化
?? ?p->data = data; ? ? //存儲數據
?? ?p->next = s->top; ? ? //新節點指向原棧頂
?? ?s->top = p; ? ? //更新棧頂指針為新節點
?? ?s->size++; ? ? //元素計數增加
?? ?
?? ?return 0;
}
/**
?* 判斷棧是否為空
?* @param s 棧結構體指針(需由調用者提前分配內存)
?* @return 棧為空返回1
?*/
int lstack_isempty(LinkStack *s)
{
?? ?if(!s)
?? ??? ?return 1; ? ? //空指針視為空棧
?? ?
?? ?return s->size == 0;
?? ?//return s->top = NULL;
}
/**
?* 出棧
?* @param s 棧結構體指針(需由調用者提前分配內存)
?* @param data 接收出棧的數據指針
?* @return 成功返回0,否則返回-1
?*/
int lstack_pop(LinkStack *s, DATA *data)
{
?? ?if(!s || !data)
?? ?{
?? ??? ?perror("Stack is empty!");
?? ??? ?return -1;
?? ?}
?? ?
?? ?//判斷棧是否為空
?? ?if(lstack_isempty(s))
?? ?{
?? ??? ?perror("警告!試圖從空棧彈出數據!");
?? ??? ?return -1;
?? ?}
?? ?
?? ?NODE *p = s->top; ? ? //保存棧頂節點
?? ?*data = p->data; ? ? //獲取彈出棧的數據
?? ?s->top = p->next; ? ? //更新棧頂指針
?? ?free(p); ? ? //釋放原棧頂節點
?? ?s->size--;
?? ?
?? ?return 0;
}
/**
?* 銷毀棧
?*/
void lstack_destroy(LinkStack *s)
{
?? ?if(!s)?
?? ??? ?return; ? ? //空指針保護
?? ?
?? ?DATA temp; ? ? //臨時存儲彈出數據
?? ?
?? ?//釋放所有節點
?? ?while(!lstack_isempty(s))
?? ?{
?? ??? ?lstack_pop(s, &temp); ? ? //彈出數據存入temp
?? ?}
?? ?return;
}
```
##### app.c
#include "linkstack.h"
int main(int argc, char const *argv[])
{
? ? LinkStack s;
? ? DATA temp;
? ? // 1. 初始化容量為10的鏈式棧
? ? lstack_init(&s, 10);
? ? // 2. 入棧測試
? ? printf("入棧順序:");
? ? for (int i = 0; i < 10; i++)
? ? {
? ? ? ? lstack_push(&s, i + 10); // 壓入10~19
? ? ? ? printf("%d ", i + 10);
? ? }
? ? printf("\n");
? ? // 測試棧滿
? ? if (lstack_push(&s, 20) == -1)
? ? ? ? printf("棧已滿,插入20失敗\n");
? ? // 3. 出棧測試
? ? printf("出棧順序:");
? ? while (!lstack_isempty(&s))
? ? {
? ? ? ? lstack_pop(&s, &temp);
? ? ? ? printf("%d ", temp);
? ? }
? ? printf("\n");
? ? // 測試棧空
? ? if (lstack_pop(&s, &temp) == -1)
? ? ? ? printf("棧已空,無法彈出\n");
? ? // 4. 銷毀棧
? ? lstack_destroy(&s);
? ? return 0;
}