目录
1.顺序栈
说明:本篇代码中,顺序栈栈顶指针初始值为 -1,代码中,数组采用的是 int 类型的指针,指向一块通过malloc 开辟的内存空间。也可以通过 Elemtype data[MAXSIZE] 指定。
(1)数据结构
#define MAXSIZE 100
typedef int Elemtype;
typedef struct SqStack
{
//Elemtype data[MAXSIZE];
Elemtype* data; //指向一块内存
int top; //栈顶指针
}SqStack;
(2)函数列表
1.初始化栈
//初始化栈
SqStack* Init_Stack()
{
/*1.为结构体分配内存*/
SqStack* Sq = (SqStack*)malloc(sizeof(SqStack));
/*2.初始化数据指针*/
Sq->data = (Elemtype*)malloc(sizeof(Elemtype) * MAXSIZE);
/*3.初始化栈顶指针*/
Sq->top = -1;
return Sq;
}
2.判空
注:判空时需要先判断头节点是否存在,即:判断头节点是否为空,再判断是否有元素。顺序不能反转。因为当头节点未定义时,使用 Sq->top 会造成空指针的引用,引发段错误。
//判断一个栈是否为空
bool Stack_Is_Empty(SqStack* Sq)
{
/*1.判断头节点是否为空*/
if (Sq == NULL)
{
printf("栈未定义!\n");
return true;
}
/*2.判断是否有元素*/
if (Sq->top == -1)
{
return true;
}
return false;
}
3.出栈
//出栈
bool Pop(SqStack* Sq, Elemtype* d)
{
/*1.判空*/
if (Stack_Is_Empty(Sq))
{
printf("栈为空\n");
return false;
}
/*2.出栈*/
*d = Sq->data[Sq->top--]; // 修正这里的顺序
return true;
}
4.入栈
注:元素入栈前,需要先判空,再判断栈是否已经满了,不能颠倒顺序,栈空时可能造成使用空指针的情况。
//入栈
bool Push(SqStack* Sq, Elemtype d)
{
/*1.判空*/
if (Sq == NULL)
{
printf("栈为空\n");
return false;
}
/*2.判满*/
if (Sq->top == MAXSIZE - 1)
{
printf("栈满,无法入栈!\n");
return false;
}
/*3.入栈*/
Sq->top += 1;
Sq->data[Sq->top] = d; // 修正这里的顺序
return true;
}
5.返回栈中元素个数
注:数组下标从 0 开始,栈底默认为 -1 所以元素的个数需要在 top 的基础上 +1
//返回栈的元素个数
int Get_Stack_Length(SqStack* Sq)
{
/*1.判空*/
if (Stack_Is_Empty(Sq))
{
printf("栈为空\n");
return 0;
}
return Sq->top + 1;
}
6.返回栈顶元素
//返回栈顶元素
bool Get_Top(SqStack* Sq, Elemtype* d)
{
/*1.判空*/
if (Stack_Is_Empty(Sq))
{
printf("栈为空\n");
return false;
}
*d = Sq->data[Sq->top];
return true;
}
7.清空栈
注:直接重置 top 为 -1 即可,top 作为栈顶指针,元素读取超过 top 都是 "越界" 的情况,不考虑。新的数据会覆盖老的数据,不会造成影响。
//清空一个栈
void Clear_Stack(SqStack* Sq)
{
/*1.判空*/
if (Stack_Is_Empty(Sq))
{
printf("栈为空\n");
return;
}
/*2.重置 data 数组*/
Sq->top = -1;
}
8.销毁栈
注:data 数组也是通过 malloc 在堆区创建的,需要手动释放,并且先与 Sq 头指针释放,否则先释放了 Sq 头指针,再去释放 data 所指向的内存可能会造成未知结果。因为 Sq 已经被释放,Sq 不一定还存有 data 的地址,或 Sq 已经被置空,造成空指针引用,引发段错误。
//销毁栈
SqStack* Destory_Stack(SqStack* Sq)
{
/*1.判空*/
if (Sq == NULL)
return NULL;
/*2.释放结点*/
free(Sq->data);
Sq->data = NULL;
free(Sq);
Sq = NULL;
return Sq;
}
9.打印栈
注:栈是先进后出的线性结构,这里通过 for 循环遍历,只是为了验证代码是否准确。
//打印栈
void Print_SqStack(SqStack* Sq)
{
printf("\n打印栈:\n");
printf("------------------------\n");
if (Stack_Is_Empty(Sq))
{
printf("栈空!");
}
else
{
for (int i = 0; i <= Sq->top; i++)
{
printf("%d ", Sq->data[i]);
}
}
printf("\n------------------------\n");
}
(3)完整代码
#include<stdio.h>
#include<stdbool.h>
#define MAXSIZE 100
typedef int Elemtype;
typedef struct SqStack
{
//Elemtype data[MAXSIZE];
Elemtype* data; //指向一块内存
int top; //栈顶指针
}SqStack;
//初始化栈
SqStack* Init_Stack()
{
/*1.为结构体分配内存*/
SqStack* Sq = (SqStack*)malloc(sizeof(SqStack));
/*2.初始化数据指针*/
Sq->data = (Elemtype*)malloc(sizeof(Elemtype) * MAXSIZE);
/*3.初始化栈顶指针*/
Sq->top = -1;
return Sq;
}
//判断一个栈是否为空
bool Stack_Is_Empty(SqStack* Sq)
{
/*1.判断头节点是否为空*/
if (Sq == NULL)
{
printf("栈未定义!\n");
return true;
}
/*2.判断是否有元素*/
if (Sq->top == -1)
{
return true;
}
return false;
}
//出栈
bool Pop(SqStack* Sq, Elemtype* d)
{
/*1.判空*/
if (Stack_Is_Empty(Sq))
{
printf("栈为空\n");
return false;
}
/*2.出栈*/
*d = Sq->data[Sq->top--]; // 修正这里的顺序
return true;
}
//入栈
bool Push(SqStack* Sq, Elemtype d)
{
/*1.判空*/
if (Sq == NULL)
{
printf("栈为空\n");
return false;
}
/*2.判满*/
if (Sq->top == MAXSIZE - 1)
{
printf("栈满,无法入栈!\n");
return false;
}
/*3.入栈*/
Sq->top += 1;
Sq->data[Sq->top] = d; // 修正这里的顺序
return true;
}
//返回栈的元素个数
int Get_Stack_Length(SqStack* Sq)
{
/*1.判空*/
if (Stack_Is_Empty(Sq))
{
printf("栈为空\n");
return 0;
}
return Sq->top + 1;
}
//返回栈顶元素
bool Get_Top(SqStack* Sq, Elemtype* d)
{
/*1.判空*/
if (Stack_Is_Empty(Sq))
{
printf("栈为空\n");
return false;
}
*d = Sq->data[Sq->top];
return true;
}
//清空一个栈
void Clear_Stack(SqStack* Sq)
{
/*1.判空*/
if (Stack_Is_Empty(Sq))
{
printf("栈为空\n");
return;
}
/*2.重置 data 数组*/
Sq->top = -1;
}
//销毁栈
SqStack* Destory_Stack(SqStack* Sq)
{
/*1.判空*/
if (Sq == NULL)
return NULL;
/*2.释放结点*/
free(Sq->data);
Sq->data = NULL;
free(Sq);
Sq = NULL;
return Sq;
}
//打印栈
void Print_SqStack(SqStack* Sq)
{
printf("\n打印栈:\n");
printf("------------------------\n");
if (Stack_Is_Empty(Sq))
{
printf("栈空!");
}
else
{
for (int i = 0; i <= Sq->top; i++)
{
printf("%d ", Sq->data[i]);
}
}
printf("\n------------------------\n");
}
int main()
{
//创建栈
SqStack* Sq = Init_Stack();
//判空
Stack_Is_Empty(Sq);
//入栈测试
printf("1 2 3 4 5入栈\n");
Push(Sq, 1);
Push(Sq, 2);
Push(Sq, 3);
Push(Sq, 4);
Push(Sq, 5);
//输出元素个数
printf("栈中有 %d 个元素\n", Get_Stack_Length(Sq));
Print_SqStack(Sq);
//获取栈顶元素
Elemtype data;
Get_Top(Sq, &data);
printf("栈顶元素为:%d", data);
//出栈
printf("\n\n出栈两个元素\n");
Pop(Sq, &data);
printf("出栈:%d\n", data);
Pop(Sq, &data);
printf("出栈:%d\n", data);
Print_SqStack(Sq);
//获取栈顶元素
Get_Top(Sq, &data);
printf("栈顶元素为:%d\n", data);
//清空栈
printf("\n清空栈");
Clear_Stack(Sq);
//判空
Stack_Is_Empty(Sq);
Print_SqStack(Sq);
//销毁栈
printf("\n销毁栈");
Sq = Destory_Stack(Sq);
Print_SqStack(Sq);
return 0;
}
(4)运行结果
2.链式栈
(1)数据结构
注:代码使用的是带头节点的双向链表模型作为栈。链表的头结点作为栈底
typedef int Elemtype;
typedef struct Node
{
Elemtype data;
struct Node* next;
struct Node* prev;
}Node;
//头节点做栈顶
typedef struct LinkStack
{
Node* top; //指向栈顶
Node* bottom; //指向栈底
int length; //元素数量
}LinkStack;
(2)函数列表
1.初始化栈
//初始化一个栈
LinkStack* Init_Stack()
{
/*1.初始化头节点*/
LinkStack* Link = (LinkStack*)malloc(sizeof(LinkStack));
Link->top = NULL;
Link->bottom = NULL;
Link->length = 0;;
return Link;
}
2.判空
//判断一个栈是否为空
bool Stack_Is_Empty(LinkStack* LS)
{
if (LS == NULL || LS->bottom == NULL)
{
printf("栈空\n");
return true;
}
return false;
}
3.入栈
//入栈
bool Push(LinkStack* LS,Elemtype d)
{
/*1.判空*/
if (LS == NULL)
{
printf("栈空!\n");
return false;
}
/*2.创建结点*/
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = d;
newNode->next = NULL;
newNode->prev = NULL;
/*3.插入元素*/
if (LS->top == NULL)
{ //链表中没有结点
LS->top = newNode;
LS->bottom = newNode;
}
else
{ //首结点做栈顶,头插
LS->top->prev = newNode;
newNode->next = LS->top;
LS->top = newNode;
}
LS->length++;
return true;
}
4.出栈
//出栈
bool Pop(LinkStack* LS, Elemtype *d)
{
/*1.判空*/
if (Stack_Is_Empty(LS))
{
printf("栈空\n");
return false;
}
/*2.获取结点的值*/
*d = LS->top->data;
/*3.出栈、释放空间*/
Node* p = LS->top;
LS->top = p->next;
/*4.判断链表是否还有结点*/
if(LS->top != NULL)
LS->top->prev = NULL;
else
{
LS->top = NULL;
LS->bottom = NULL;
}
free(p);
p = NULL;
LS->length--;
return true;
}
5.返回栈中元素个数
//返回栈的元素个数
int Get_Stack_Length(LinkStack* LS)
{
if (Stack_Is_Empty(LS))
{
printf("空栈\n");
return 0;
}
return LS->length;
}
6.返回栈顶元素
//返回栈顶元素
void Get_Stack_Top(LinkStack* LS,Elemtype *d)
{
if (Stack_Is_Empty(LS))
{
printf("空栈\n");
return;
}
*d = LS->top->data;
}
7.清空栈
//清空一个栈
void Clear_Stack(LinkStack* LS)
{
/*1.判空*/
if (Stack_Is_Empty(LS))
return;
/*2.逐个释放*/
Node* p = NULL;
while (LS->top)
{
p = LS->top;
LS->top = p->next;
free(p);
p = NULL;
}
/*3.更新头节点*/
LS->bottom = NULL;
LS->top = NULL;
LS->length = 0;
}
8.销毁栈
//销毁一个栈
LinkStack* Destory_Stack(LinkStack* LS)
{
Clear_Stack(LS);
if (LS == NULL)
return LS;
free(LS);
LS = NULL;
return LS;
}
9.打印栈
//打印栈
void Print_Stack(LinkStack* LS)
{
printf("\n打印栈\n");
printf("-------------------\n");
if (Stack_Is_Empty(LS))
printf("空栈!");
else
{
Node* p = LS->top;
while (p)
{
printf("%d ", p->data);
p = p->next;
}
/*逆向打印,验证链式栈是否正确链接*/
printf("\n");
p = LS->bottom;
while (p)
{
printf("%d ", p->data);
p = p->prev;
}
}
printf("\n-------------------\n");
}
(3)完整代码
#include<stdio.h>
#include<stdbool.h>
typedef int Elemtype;
typedef struct Node
{
Elemtype data;
struct Node* next;
struct Node* prev;
}Node;
//头节点做栈顶
typedef struct LinkStack
{
Node* top; //指向栈顶
Node* bottom; //指向栈底
int length; //元素数量
}LinkStack;
//初始化一个栈
LinkStack* Init_Stack()
{
/*1.初始化头节点*/
LinkStack* Link = (LinkStack*)malloc(sizeof(LinkStack));
Link->top = NULL;
Link->bottom = NULL;
Link->length = 0;;
return Link;
}
//判断一个栈是否为空
bool Stack_Is_Empty(LinkStack* LS)
{
if (LS == NULL || LS->bottom == NULL)
{
printf("栈空\n");
return true;
}
return false;
}
//入栈
bool Push(LinkStack* LS,Elemtype d)
{
/*1.判空*/
if (LS == NULL)
{
printf("栈空!\n");
return false;
}
/*2.创建结点*/
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = d;
newNode->next = NULL;
newNode->prev = NULL;
/*3.插入元素*/
if (LS->top == NULL)
{ //链表中没有结点
LS->top = newNode;
LS->bottom = newNode;
}
else
{ //首结点做栈顶,头插
LS->top->prev = newNode;
newNode->next = LS->top;
LS->top = newNode;
}
LS->length++;
return true;
}
//出栈
bool Pop(LinkStack* LS, Elemtype *d)
{
/*1.判空*/
if (Stack_Is_Empty(LS))
{
printf("栈空\n");
return false;
}
/*2.获取结点的值*/
*d = LS->top->data;
/*3.出栈、释放空间*/
Node* p = LS->top;
LS->top = p->next;
/*4.判断链表是否还有结点*/
if(LS->top != NULL)
LS->top->prev = NULL;
else
{
LS->top = NULL;
LS->bottom = NULL;
}
free(p);
p = NULL;
LS->length--;
return true;
}
//返回栈的元素个数
int Get_Stack_Length(LinkStack* LS)
{
if (Stack_Is_Empty(LS))
{
printf("空栈\n");
return 0;
}
return LS->length;
}
//返回栈顶元素
void Get_Stack_Top(LinkStack* LS,Elemtype *d)
{
if (Stack_Is_Empty(LS))
{
printf("空栈\n");
return;
}
*d = LS->top->data;
}
//清空一个栈
void Clear_Stack(LinkStack* LS)
{
/*1.判空*/
if (Stack_Is_Empty(LS))
return;
/*2.逐个释放*/
Node* p = NULL;
while (LS->top)
{
p = LS->top;
LS->top = p->next;
free(p);
p = NULL;
}
/*3.更新头节点*/
LS->bottom = NULL;
LS->top = NULL;
LS->length = 0;
}
//销毁一个栈
LinkStack* Destory_Stack(LinkStack* LS)
{
Clear_Stack(LS);
if (LS == NULL)
return LS;
free(LS);
LS = NULL;
return LS;
}
//打印栈
void Print_Stack(LinkStack* LS)
{
printf("\n打印栈\n");
printf("-------------------\n");
if (Stack_Is_Empty(LS))
printf("空栈!");
else
{
Node* p = LS->top;
while (p)
{
printf("%d ", p->data);
p = p->next;
}
/*逆向打印,验证链式栈是否正确链接*/
printf("\n");
p = LS->bottom;
while (p)
{
printf("%d ", p->data);
p = p->prev;
}
}
printf("\n-------------------\n");
}
int main() {
LinkStack* stack = Init_Stack();
// 测试 Push
printf("入栈10,20,30,40,50\n");
for (int i = 1; i <= 5; i++) {
Push(stack, i * 10);
}
// 测试 Get_Stack_Length
printf("栈的长度:%d\n", Get_Stack_Length(stack));
// 测试 Get_Stack_Top
int data;
Get_Stack_Top(stack,&data);
// 测试 Print_Stack
Print_Stack(stack);
// 测试 Pop
printf("出栈3个元素\n");
for (int i = 0; i < 3; i++) {
Pop(stack,&data);
}
// 测试 Pop 后的 Get_Stack_Length
printf("Pop 后栈的长度:%d\n", Get_Stack_Length(stack));
// 测试 Pop 后的 Print_Stack
printf("Pop 后栈的内容:\n");
Print_Stack(stack);
// 测试 Clear_Stack
printf("清空栈\n");
Clear_Stack(stack);
// 测试 Clear_Stack 后的 Get_Stack_Length
printf("Clear_Stack 后栈的长度:%d\n", Get_Stack_Length(stack));
Print_Stack(stack);
// 测试 Clear_Stack 后的 Stack_Is_Empty
if (Stack_Is_Empty(stack)) {
printf("Clear_Stack 后栈为空。\n");
}
else {
printf("Clear_Stack 后栈不为空。\n");
}
// 测试 Destory_Stack
printf("销毁栈\n");
stack = Destory_Stack(stack);
Print_Stack(stack);
return 0;
}