> 文章列表 > 【数据结构】栈的实现

【数据结构】栈的实现

【数据结构】栈的实现

你内心肯定有有着某种火焰,能把你和其他人区别开来。                   --库切

目录 

🚗一.栈的概念及结构

🚒二.栈的基本操作 

🍗1.栈的初始化

🥩2.入栈

🍊3.栈顶的元素

🍒4.出栈

🍓5.判断栈是否为空

🍌6.栈中的元素个数

​🌶️7.销毁栈

🚙三.栈的全部代码

🍍1.Stack.h:

🥔2.Stack.c:

🍎3.test.c:


🚗一.栈的概念及结构

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除操作,进行数据的插入和删除操作的一端称为栈顶。另一端称为栈底。栈中数据元素遵循后进先出LIFO(last in first out)。

栈最基本的两个操作就是压栈和出栈。
1.压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
2.出栈:栈的删除操作叫做出栈,出数据也在栈顶。 
通俗的理解其实就是我们之前学习的尾插和尾删,尾插对应的就是压栈,尾删对应的就是出栈。
但是对于尾插,尾删,我们学习了三种结构:顺序表(数组),单链表,双链表。所以这里我们选用哪一种结构来实现栈呢?

对于单链表尾插,尾删,我们每次都需要遍历整个数组,来找到尾,再进行操作,时间复杂度是O(N),所以我们不会使用单链表来实现栈,我们可以选择顺序表(数组)或者双链表来实现。
这里我们选择的是顺序表(数组)。

和之前一样,我们使用结构体来实现:

typedef int STDataType;
typedef struct Stack
{STDataType* a;//动态数组STDataType top;//栈顶int Capacity;//容量
}ST;

🚒二.栈的基本操作 

🍗1.栈的初始化

对于栈的初始化,我们可以先使用malloc动态的给数组开辟几个空间,容量也栈初始化几个。

//初始化栈
void StackInit(ST* ps)
{assert(ps);ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);//动态的开辟空间if (ps->a == NULL){perror("malloc\\n");return;}ps->top = 0;ps->Capacity = 4;//初始化容量为4
}

🥩2.入栈

入栈也就是尾插,这是我们之前学过的,这是非常简单的。但是还是有个小细节要注意,在入栈之前,我们需要判断一下,栈内的容量是否满了,满了就要增容。

// 入栈
void StackPush(ST* ps,STDataType x)
{assert(ps);//判断是否满了if (ps->top == ps->Capacity){STDataType* temp = (STDataType*)realloc(ps->a, sizeof(STDataType) * ps->Capacity * 2);if (temp==NULL){perror("realloc\\n");return;}else{ps->Capacity *= 2;//每次增容尾上一次的二倍ps->a = temp;}	}else{ps->a[ps->top] = x;ps->top++;//栈内入一个数据,top就要往上面走一步}
}

🍊3.栈顶的元素

我们要打印栈顶的元素要怎么打印呢?当入栈已经结束了之后,我们先打印第一个栈顶的元素,然后再出栈一个,继续打印栈顶的元素,以此类推,直到栈为空。

STDataType StackTop(ST* ps) 
{assert(ps);assert(ps->top > 0);//这里要断言一下,如果栈为空,就不能打印了return ps->a[ps->top - 1];
}

🍒4.出栈

出栈也就是我们所说的尾删,数组的尾删只需要把top的位置往前挪一位就行了。

void StackPop(ST* ps)
{assert(ps);assert(ps->top > 0);ps->top--;
}

🍓5.判断栈是否为空

为什么要判断栈为空呢?因为当我们进行出栈的时候,栈内的元素为依次减小,如果减小到0,就不能继续出栈了。

//判断栈是否为空
bool StackEmpty(ST* ps)//这里我们使用bool来判断
{assert(ps);return ps->top == 0;//当ps->top为0的时候,式子成立,即返回真。反之,亦然。
}

我们就先往栈入 1  2  3  4四个数字,再依次出栈出来打印出来看看。

int main()
{ST st;StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);while (!StackEmpty(&st)){printf("%d ", StackTop(&st));StackPop(&st);}printf("\\n");return 0;
}


很明显这很符合栈的先入后出的特点。

🍌6.栈中的元素个数

我们入了几个元素,top就是机,直接把top打印出来就是栈元素的个数了。

int StackSize(ST* ps)
{assert(ps);return ps->top;
}

🌶️7.销毁栈

当我们退出程序的时候,把栈给销毁一下。

//销毁栈
void StackDestory(ST* ps)
{free(ps->a);ps->a = NULL;ps->Capacity = 0;ps->top = 0;
}

🚙三.栈的全部代码

🍍1.Stack.h:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int STDataType;
typedef struct Stack
{STDataType* a;//动态数组STDataType top;//栈顶int Capacity;//容量
}ST;//初始化栈
void StackInit(ST* ps);//入栈
void StackPush(ST* ps, STDataType x);//出栈
void StackPop(ST* ps);//栈元素的个数
int StackSize(ST* ps);//判断栈是否为空
bool StackEmpty(ST* ps);//栈顶的元素是多少
STDataType StackTop(ST* ps);//销毁栈
void StackDestory(ST* ps);

🥔2.Stack.c:
 

#define _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"
//初始化栈
void StackInit(ST* ps)
{assert(ps);ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);if (ps->a == NULL){perror("malloc\\n");return;}ps->top = 0;ps->Capacity = 4;
}// 入栈
void StackPush(ST* ps,STDataType x)
{assert(ps);//判断是否满了if (ps->top == ps->Capacity){STDataType* temp = (STDataType*)realloc(ps->a, sizeof(STDataType) * ps->Capacity * 2);if (temp==NULL){perror("realloc\\n");return;}else{ps->Capacity *= 2;ps->a = temp;}	}else{ps->a[ps->top] = x;ps->top++;}
}//出栈
void StackPop(ST* ps)
{assert(ps);assert(ps->top > 0);ps->top--;
}//栈元素的个数
int StackSize(ST* ps)
{assert(ps);return ps->top;
}//判断栈是否为空
bool StackEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}//栈顶的元素是多少
STDataType StackTop(ST* ps) 
{assert(ps);assert(ps->top > 0);return ps->a[ps->top - 1];
}//销毁栈
void StackDestory(ST* ps)
{free(ps->a);ps->a = NULL;ps->Capacity = 0;ps->top = 0;
}//打印函数
void StackPrint(ST* ps)
{assert(ps);int i = 0;while (i < ps->top){printf("%d", ps->a[i]);i++;}
}

🍎3.test.c:

#define _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"
ST st;
void Stacktest1()
{StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);while (!StackEmpty(&st)){printf("%d ", StackTop(&st));StackPop(&st);}printf("\\n");
}void Stacktest2()
{StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);printf("栈内元素的个数:\\n");printf( "%d\\n",StackSize(&st));}
int main()
{//Stacktest1();Stacktest2();return 0;
}