文章目录
- 1.栈的概念
- 2.栈的底层结构
- 3.栈的功能
- 4.栈的实现
- 4.1.栈结构的定义
- 4.2.栈的初始化
- 4.3.栈的销毁
- 4.4.入栈
- 4.5.出栈
- 4.6.取栈顶元素
- 4.7.获取栈中有效元素个数
- 5.完整代码
- Stack.h
- Stack.c
- main.c
- 运行结果
1.栈的概念
是一种特殊的线性表,只允许数据在固定的一段进行插入、删除元素的操作
- 我们把进行插入或删除元素的一端成为栈顶,另一端成为栈底
- 栈中的元素遵循先进后出原则
- 入栈:在栈顶插入元素,又称压栈/进栈
- 出栈:删除栈顶元素
2.栈的底层结构
思考:栈是一种线性表,只在一端进行插入或删除操作,因此我们可以选择用数组(顺序表)或链表来作为它的底层结构,那么用哪个更优呢?
时间复杂度分析:
数组:相当于在末尾添加或删除元素
入栈:O(1) 出栈:O(1)
链表:把表头当作栈顶,相当于头插或头删,需要从头节点遍历到尾节点
入栈:O(1) 出栈:O(1)
综上,时间复杂度相等
空间复杂度分析:
数组:每次扩容需要开辟相应倍数数据类型大小的空间(每次扩容乘2)
链表:每添加一个元素需要开辟相应节点大小的空间
综上,显然数组的空间复杂度更低
因此,我们通常选择数组来作为栈的底层结构
3.栈的功能
主要功能有:入栈、出栈、取栈顶元素、返回栈中有效元素个数
4.栈的实现
4.1.栈结构的定义
定义一个栈的结构体,其中的成员变量包含:数组(指针)、有效元素个数、数组容量
//栈的结构
typedef int STDataType;//栈中存储的变量类型
typedef struct Stack{STDataType* a;//变长数组,存储数据int top;//记录有效元素个数int capacity;//数组容量
}ST;
4.2.栈的初始化
创建一个空数组
void STInit(ST* ps)
{ps->a = NULL;ps->capacity = ps->top = 0;
}
4.3.栈的销毁
释放栈中数组空间,把成员变量都置为空
void STDestroy(ST* ps)
{assert(ps);if(ps->a) free(ps->a);ps->a = NULL;ps->top = ps->capacity = 0;
}
4.4.入栈
在栈顶,即数组末尾插入元素
void STPush(ST* ps, STDataType x)
{assert(ps);//判断空间是否足够-扩容if(ps->top == ps->capacity){int newCapacity = ps->capacity == 0 ? 4 : 2*ps->capacity;STDataType* tmp = (STDataType*)realloc(ps->a, newCapacity * sizeof(STDataType));//扩容失败if(tmp == NULL){perror("Realloc Failed!\n");exit(1);}ps->a = tmp;ps->capacity = newCapacity;}//空间足够ps->a[ps->top++] = x;
}
4.5.出栈
在栈顶,即数组末尾删除元素
需要先判断栈是否为空,写一个判空函数:
bool STEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}
出栈的实现:
void STPop(ST* ps)
{assert(!STEmpty(ps));ps->top--;
}
4.6.取栈顶元素
返回数组中top-1位置的元素值即可
STDataType STTop(ST* ps)
{assert(!STEmpty(ps));return ps->a[ps->top-1];
}
4.7.获取栈中有效元素个数
返回top值即可
int STSize(ST* ps)
{assert(!STEmpty(ps));return ps->top;
}
5.完整代码
Stack.h
//
// Stack.h
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>//栈的结构
typedef int STDataType;//栈中存储的变量类型
typedef struct Stack{STDataType* a;//变长数组,存储数据int top;//记录有效元素个数int capacity;//数组容量
}ST;//初始化
void STInit(ST* ps);
//销毁
void STDestroy(ST* ps);//入栈
void STPush(ST* ps, STDataType x);//判空
bool STEmpty(ST* ps);//出栈
void STPop(ST* ps);//取栈顶元素
STDataType STTop(ST* ps);//有效元素个数
int STSize(ST* ps);
Stack.c
//
// Stack.c
#include "Stack.h"void STInit(ST* ps)
{ps->a = NULL;ps->capacity = ps->top = 0;
}
void STDestroy(ST* ps)
{assert(ps);if(ps->a) free(ps->a);ps->a = NULL;ps->top = ps->capacity = 0;
}void STPush(ST* ps, STDataType x)
{assert(ps);//判断空间是否足够-扩容if(ps->top == ps->capacity){int newCapacity = ps->capacity == 0 ? 4 : 2*ps->capacity;STDataType* tmp = (STDataType*)realloc(ps->a, newCapacity * sizeof(STDataType));//扩容失败if(tmp == NULL){perror("Realloc Failed!\n");exit(1);}ps->a = tmp;ps->capacity = newCapacity;}//空间足够ps->a[ps->top++] = x;
}bool STEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}void STPop(ST* ps)
{assert(!STEmpty(ps));ps->top--;
}STDataType STTop(ST* ps)
{assert(!STEmpty(ps));return ps->a[ps->top-1];
}int STSize(ST* ps)
{assert(!STEmpty(ps));return ps->top;
}
main.c
//main.c
#include "Stack.h"void test(void)
{ST st;STInit(&st);STPush(&st, 1);STPush(&st, 2);STPush(&st, 3);STPush(&st, 4);printf("st size: %d\n", STSize(&st));while(!STEmpty(&st)){STDataType top = STTop(&st);STPop(&st);printf("%d ", top);}printf("\n");STDestroy(&st);
}
int main(void)
{test();return 0;
}