今天,本尊给你们介绍一下栈!
栈的数据结构定义
栈是一种线性的数据结构,遵循 后进先出(LIFO, Last In First Out) 的原则。这意味着最后被压入栈中的元素会最先弹出。栈的操作通常包括 push
(入栈)、pop
(出栈)以及查看栈顶元素的 top
或者 peek
。
通过两种主要方式可以实现栈:基于数组的方式和基于链表的方式。
基于数组的栈实现
以下是基于数组的栈的具体实现方法:
typedef int STDataType;
// 定义栈结构
typedef struct stack {
STDataType* a; // 指向存储数据的动态数组
int top; // 当前栈顶位置索引
int capacity; // 栈的最大容量
} ST;
上述代码片段中,a
是一个指向动态分配内存区域的指针,用于保存栈内的数据;top
表示当前栈顶的位置索引;capacity
则表示该栈能够容纳的最大元素数量1。
初始化函数
初始化栈时需要为其分配初始容量并设置默认参数:
void StackInit(ST* pst) {
assert(pst);
pst->a = malloc(sizeof(STDataType) * 4); // 默认分配4个单位的空间
if (pst->a == NULL) exit(-1); // 如果分配失败则退出程序
pst->top = 0; // 栈为空时,top=0
pst->capacity = 4; // 设置初始容量为4
}
此部分实现了栈对象的初始化操作,其中使用了 malloc()
函数来动态申请内存空间,并设置了栈的初始状态。
动态扩容机制
当栈满时需扩展其容量以便继续存入新元素:
void StackExpand(ST* pst) {
assert(pst);
// 创建新的更大的连续内存块
STDataType* tmp = realloc(pst->a, sizeof(STDataType) * pst->capacity * 2);
if (tmp == NULL) exit(-1); // 扩展失败处理
pst->a = tmp; // 更新原地址至扩增后的内存区
pst->capacity *= 2; // 叠加两倍原有容量作为新的总容量
}
这里展示了如何利用 C 库函数 realloc()
对已有堆上分配的对象进行尺寸调整的过程。
入栈与出栈功能
分别提供两个接口完成基本的功能需求:
Push(入栈)
将指定数值加入到栈顶端:
void StackPush(ST* pst, STDataType x){
if (pst->top == pst->capacity){ // 若已达到上限,则触发自动增长逻辑
StackExpand(pst);
}
pst->a[pst->top++] = x; // 将传入值赋给对应下标的单元格后再自增计数器
}
Pop(出栈)
移除位于顶部的那个项目并将它返回给调用方:
STDataType StackPop(ST* pst){
assert(pst && pst->top > 0); // 验证合法性前提条件成立与否
return pst->a[--pst->top]; // 自减计数器之后读取旧版最高层记录的内容
}
基于链表的栈实现
另一种常见的做法是以单项链表的形式构建栈模型。下面给出具体实例说明:
节点类型声明
#include <stdio.h>
#include <stdlib.h>
typedef int data_t;
// 单项节点定义
typedef struct node{
data_t data; // 存储实际信息字段
struct node *next; // 下一结点链接指示符
} listnode,*linkstack;
此处我们重新设计了一个简单的单项列表节点形式,准备用来搭建我们的目标容器体系2.
构造空栈过程
linkstack sqtack_create(void){
linkstack sq;
sq=(linkstack )malloc(sizeof(listnode));
if(!sq){
printf("Memory allocation failure!\n");
return NULL;
}
sq->data=0; // 记录长度初设为零
sq->next=NULL; // 清理后续连接关系标志位
return sq;
}
这段源码负责开辟一块固定大小的新区块供作头哨兵角色之用途,同时将其内部属性置成合理初识形态.
插入动作执行流程
每当有新增请求到达时,就依照既定规则把待加工材料挂载上去即可满足业务诉求。
int push(linkstack s,data_t val){
linkstack new_node=(linkstack)calloc(1,sizeof(*new_node));
if(new_node==NULL)return -1;
new_node->data=val;
new_node->next=s->next;
s->next=new_node;
++s->data;
return 0;
}
同理可得删除环节亦然简单明了很多呢!