一、什么是堆栈
首先,我们要理解堆栈的含义。
堆栈是一个特定的存储区或寄存器,它的一端是固定的,另一端是浮动的 。对这个存储区存入的数据,是一种特殊的数据结构。所有的数据存入或取出,只能在浮动的一端(称栈顶)进行,严格按照“先进后出”的原则存取,位于其中间的元素,必须在其栈上部(后进栈者)诸元素逐个移出后才能取出。
二、堆栈结构体的基本形态
typedef struct Stack{
T* m_vect; //存储元素内存空间
size_t size; //堆栈总容量
size_t index;//堆栈中已经存储元素的个数
}Stack;
以上是堆栈结构体的基本组成部分。
三、实现堆栈需要包含的头文件
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
四、堆栈的主要相关函数
//初始化堆栈 申请动态内存
void init(Stack *stack,size_t size);
//把data这个元素放到堆栈中去
void push(Stack *stack,T data);
//从堆栈中取到一个元素 该元素是最后放到堆栈中那个元素
T pop(Stack *stack);
//查看堆栈顶的元素 并不拿走
T peek(Stack *stack);
//堆栈是否为空
bool isEmpty(Stack *stack);
//堆栈中存储元素的个数
size_t getCnt(Stack *stack);
//堆栈中容量的大小
size_t getSize(Stack *stack);
//堆栈是否已经满了
bool isFull(Stack *stack);
//清空堆栈
void clear(Stack *stack);
//销毁堆栈
void destroy(Stack *stack);
//遍历一下堆栈中的元素
void travel(Stack *stack);
五、相关函数的实现
//为了便于今后开发过程中对于数据类型的修改,此处将T代表int类型
typedef int T;
//初始化堆栈 申请动态内存
void init(Stack *stack,size_t size){
stack->m_vect = calloc(size,sizeof(T));
stack->size = size;
stack->index = 0;
}
//把data这个元素放到堆栈中去
void push(Stack *stack,T data){
stack->m_vect[stack->index] = data;
stack->index++;
}
//从堆栈中取到一个元素 该元素是最后放到堆栈中那个元素
T pop(Stack *stack){
return stack->m_vect[--stack->index];
}
//查看堆栈顶的元素 并不拿走
T peek(Stack *stack){
return stack->m_vect[stack->index-1];
}
//堆栈是否为空
bool isEmpty(Stack *stack){
return stack->index == 0;
}
//堆栈中存储元素的个数
size_t getCnt(Stack *stack){
return stack->index;
}
//堆栈中容量的大小
size_t getSize(Stack *stack){
return stack->size;
}
//堆栈是否已经满了
bool isFull(Stack *stack){
return stack->size == stack->index;
}
//销毁堆栈
void destroy(Stack *stack){
if(stack->m_vect != NULL){
free(stack->m_vect);
stack->m_vect = NULL;
}
}
//清空堆栈中的元素
void clear(Stack *stack){
while(!isEmpty(stack)){
pop(stack);
}
}
//遍历一下堆栈中的元素
void travel(Stack *stack){
for(int i=0;i<stack->index;i++){
printf("%d ",stack->m_vect[i]);
}
printf("\n");
}
六、堆栈进阶功能
判断brr是否是arr作为入栈的出栈顺序
bool isOutOfStack(T arr[],T brr[],size_t len){
Stack s;
init(&s,len);
int j = 0;//记录brr[]数组下标位置
for(int i=0;i<len;i++){
push(&s,arr[i]);//把入栈元素依次入栈
while(!isEmpty(&s) && peek(&s)==brr[j]){//一旦栈顶元素等于出栈元素
pop(&s);//出栈
j++; //下一个出栈元素
}
}
bool flag = isEmpty(&s);//栈里面元素全部都出列了
destroy(&s);
return flag;
}
七、堆栈的使用示例
int main(){
Stack s;
init(&s,10);
push(&s,5);
push(&s,3);
push(&s,2);
int x = pop(&s);
printf("%d\n",x);
x = pop(&s);
printf("%d\n",x);
push(&s,10);
x = pop(&s);
printf("%d\n",x);
destroy(&s);
int arr[5] = {1,2,3,4,5};
int brr[5] = {5,4,3,1,2};
if(isOutOfStack(arr,brr,5)){
printf("是\n");
}else{
printf("否\n");
}
return 0;
}
八、注意事项
大家要注意,堆栈的大小是有限的,是在建立堆栈的时候确定下来的。
堆栈的本质是按照先进后出的方式,在一个固定大小的空间中存储和读取数据,而不是像链表这样不断地去申请更大的内存空间来存放数据,这两者有本质的不同。