4.检测栈是否为空
栈为空返回true,不为空返回false
bool STEmpty(ST* pst)//栈为空返回true,不为空返回false { //写法一 //assert(pst); //if (pst->top == 0) //{ // return true; //} //else //{ // return false; //} //写法二 return pst->top == 0; }
- 当栈为空时,表示栈中没有任何元素。此时,栈顶指针 top 的值通常被设置为特定的初始值(例如0或-1),指向栈底或栈外。在这种情况下,栈顶指针没有指向有效的元素,因此栈被认为是空的。
- 当栈非空时,表示栈中至少有一个元素。此时,栈顶指针top的值指向栈顶元素的位置。栈顶元素是最后一个被入栈的元素,也是最先被访问或移除的元素。只要栈中有元素存在,栈顶指针都会指向有效的位置。
因此,在STEmpty(ST* pst)函数中,当栈为空时,即栈顶指针top的值为0(或其他特定初始值),我们返回 true 表示栈为空。反之,如果栈非空,即栈顶指针 top 的值大于0,我们返回 false 表示栈不为空。
5.出栈
先用assert判断传过来的pst指针是否指向NULL。接着判断栈是否为NULL,为NULL,STEmpty(pst)返回true,!STEmpty(pst)就是false,断言失败,程序终止。反之断言成功,程序正常执行。
图解:
void STPop(ST* pst) { assert(pst); assert(!STEmpty(pst)); pst->top--; }
【注意事项】
接着将指向栈顶的指针--,通过将栈顶指针top减一,可以将指针向栈底方向移动,从而使栈顶指向下一个元素。
指针的移动并不会直接导致元素的销毁。指针的移动只是改变了栈顶指针的位置,使其指向了栈中的下一个元素。元素本身并不会被销毁,只是在后续的操作中,可能无法直接访问被移除的元素。
6.获取栈顶元素
图解:因为前面定义的时候pst->top=0,表示指向栈顶元素的下一个位置。
pst->top-1表示栈顶元素在数组中的索引。
STDataType STTop(ST* pst) { assert(pst); assert(!STEmpty(pst)); return pst->a[pst->top - 1]; }
需要注意的是,在实际使用中,应确保栈不为空(即栈中有元素存在),才能执行取栈顶元素的操作。因此,在代码中使用了 assert(!STEmpty(pst)) 进行栈非空的断言校验。
代码执行:
7.获取栈中有效元素个数
图解:由图看出,pst->top此时是指向下标为4的位置的,所以栈此时的有效个数就为4
int STSize(ST* pst) { assert(pst); return pst->top; }
代码执行:
完整代码
Test.c
#define _CRT_SECURE_NO_WARNINGS 1 #include"Stack.h" void TestStack1() { ST st; STInit(&st); STPush(&st, 1); STPush(&st, 2); STPush(&st, 3); STPush(&st, 4); while (!STEmpty(&st)) { printf("%d ", STTop(&st));//栈顶元素 STPop(&st); } STDestroy(&st); } void TestStack2() { ST st; STInit(&st); STPush(&st, 1); STPush(&st, 2); printf("%d ", STTop(&st)); STPush(&st, 3); STPush(&st, 4); printf("\n"); printf("%d ", STTop(&st)); //printf("%d", STSize(&st)); //while (!STEmpty(&st)) //{ // printf("%d ", STTop(&st));//栈顶元素 // STPop(&st); //} STDestroy(&st); } void TestStack3() { ST st; STInit(&st); STPush(&st, 1); STPush(&st, 2); STPush(&st, 3); STPush(&st, 4); //printf("%d", STSize(&st)); STDestroy(&st); } int main() { TestStack1();//入栈出栈 //TestStack2();//获取栈顶元素 //TestStack3();//计算栈中有效元素个数 return 0; }
Stack.h
#pragma once #include<stdlib.h> #include<assert.h> #include<stdbool.h> #include<stdio.h> typedef int STDataType; typedef struct Stack { STDataType* a; int top;//栈顶的位置 int capacity;//栈的容量 }ST; void STInit(ST* pst); void STDestroy(ST* pst); void STPush(ST* pst,STDataType x); void STPop(ST* pst); STDataType STTop(ST* pst); bool STEmpty(ST* pst); int STSize(ST*pst);
Stack.c
#define _CRT_SECURE_NO_WARNINGS 1 #include"Stack.h" void STInit(ST* pst) { assert(pst); pst->a = NULL;//栈底 //top不是下标 //pst->top=-1;//指向栈顶元素 pst->top = 0;//指向栈顶元素的下一个位置 pst->capacity = 0; } void STDestroy(ST* pst) { assert(pst); free(pst->a); pst->a = NULL; } void STPush(ST* pst,STDataType x) { if (pst->top == pst->capacity) { int newCapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;//true,4.false,括2倍 STDataType* tmp = (STDataType*)realloc(pst->a, newCapacity * sizeof(STDataType));//返回值地址相等就是原地扩容,不同就是异地扩 if (tmp == NULL) { perror("realloc fail"); return; } pst->a = tmp;//返回的是realloc出来的内存块的地址 pst->capacity = newCapacity;//把扩容后的空间大小赋值给栈容量 } pst->a[pst->top] = x;//先放值 pst->top++;//再++ } void STPop(ST* pst) { assert(pst); assert(!STEmpty(pst)); pst->top--; } STDataType STTop(ST* pst) { assert(pst); assert(!STEmpty(pst)); return pst->a[pst->top - 1]; } bool STEmpty(ST* pst)//栈为空返回true,不为空返回false { //assert(pst); //if (pst->top == 0) //{ // return true; //} //else //{ // return false; //} return pst->top == 0; } int STSize(ST* pst) { assert(pst); return pst->top; }
栈面试题还在持续更新中,感谢支持!