栈是一个重要的数据结构,具有先进后出(Last In, First Out)的特性。在 STL(Standard Template Library)中,栈是一个常用的容器,本文将深入探讨如何使用C语言模拟实现 STL 中栈的所有功能。通过详细的代码实现和解释,读者将能够理解栈的基本概念以及如何在C语言中实现栈的各种操作。
上面是 STL 中栈的基本功能,包括栈的大小、容量、压栈、出栈等基本操作。由于C++中定义类可以直接类内定义构造函数来实现创建对象同时实现初始化,所以我们利用C语言模拟实现时需要提供初始化功能函数给定义的 Stack 对象初始化。
typedef int STDataType;
typedef long long LL;
typedef struct Stack
{
STDataType* a; // 利用动态数组实现线性栈
LL top;
LL capacity;
}ST;
void STInit(ST* pst)
{
assert(pst);
pst->a = NULL;
pst->capacity = 0;
pst->top = -1; // 对应 size 值为 top+1
}
注意: 这里初始状态top值的设置可分为0和-1两种思路,top = 0 时后续取定size值时直接对应 size = top,但是取栈顶类似操作时实际下标为 top-1,而设定 top = -1 时虽然top下标对应元素就是栈顶元素,但是取size值时又需要 top+1,各有利弊。这里不妨选择 -1 作为 top 初始值。
由于利用动态数组模拟栈,数据插入达到一定值时难免出现开辟出容量不够用的问题,所以引入扩容函数对栈结构体类型变量的容量进行增扩操作,代码实现如下:
bool ExpendCapacity(ST* pst)
{
if (pst->capacity - pst->top == 1)
{
LL new_capacity = (pst->capacity == 0) ? 4 : pst->capacity * 2;
STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * new_capacity);
if (tmp)
{
pst->a = tmp;
pst->capacity = new_capacity;
}
else { perror("ExpendCapacity::realloc fail"); return false; }
}
return true;
}
注意第7行if语句,我们需要中间变量tmp接收 realloc() 返回值,判断是否为空,若为空则表明申请堆区空间失败,非空再赋值给动态数组。
先检查容量,再压入元素
void STPush(ST* pst, STDataType x)
{
assert(pst);
if (!ExpendCapacity(pst))
{
return;
}
pst->a[++(pst->top)] = x;
}
注意对 top 值的处理,由于初始化 top 取值为-1,所以压栈操作 top 应该先增再放。
bool ST_IsEmpty(ST* pst)
{
assert(pst);
return (pst->top == -1);
}
void STPop(ST* pst)
{
assert(pst);
assert(!ST_IsEmpty(pst));
pst->top--;
}
注意判别栈是否为空,为空则抛出异常。
STDataType STTop(ST* pst)
{
assert(pst);
assert(!ST_IsEmpty(pst));
return pst->a[pst->top]; // 非空时top的值直接可以作下标使用
}
size_t STSize(ST* pst)
{
assert(pst);
return pst->top + 1;
}
由于利用动态数组模拟栈,切记使用结束后需要回收堆区空间,以免造成内存泄漏。
void STDestory(ST* pst)
{
assert(pst);
free(pst->a);
pst->top = -1;
}
测试代码:
void test1()
{
ST st;
STInit(&st);
STPush(&st, 1);
STPush(&st, 2);
STPush(&st, 3);
STPush(&st, 4);
STPush(&st, 5);
printf("Stack's size = %lld\n", STSize(&st));
while (!ST_IsEmpty(&st))
{
printf("%d\t", STTop(&st));
STPop(&st);
}
printf("\n");
STDestory(&st);
}
运行结果:
我们逐步介绍C语言中栈的模拟实现代码。首先,我们定义了栈的数据结构,然后实现了栈的初始化、压栈、出栈等基本操作。代码的详细解释将帮助读者理解每个函数的作用和实现原理。还讨论了代码中的性能优化点,特别是在动态扩展栈容量时的策略。此外,我们强调了异常处理的重要性,介绍了在代码中的错误处理机制,例如内存分配失败时的处理方法。
通过本文的阅读,读者不仅能够了解栈的基本概念和在计算机科学中的应用,还能够掌握在C语言中模拟实现STL中栈的所有功能。