栈及其实现(附完整代码实现)

本文详细介绍了栈这种线性数据结构,包括栈的性质、基本操作(如初始化、压栈、弹栈、获取栈顶元素等)、栈的满栈和空栈判断,以及栈在实际问题中的应用实例——判断有效括号。同时提到了栈的内存管理,以动态内存分配为例。
摘要由CSDN通过智能技术生成

栈(附完整代码实现)

性质

  1. 栈是一种特殊的线性结构,与线性表不同,栈只能在一端进行操作,另外一端锁死,是操作受限的线性表
  2. 只能在栈顶进行数据的插入和删除
  3. 遵从FILO原则,先进后出,最先进栈的元素在最底部,最后的在栈顶(空箱子放物品)

  1. 常用操作
  2. 初始化栈
  3. 压栈(入栈),添加一个元素
  4. 弹栈(出栈),删除一个元素
  5. 获取栈顶元素
  6. 判断栈是否为空,是否满栈
  7. &在操作的时候,避免上溢下溢&

上溢:指栈已满,若继续存数据,则会上溢,出现报错(栈满再存出现上溢)
下溢:指栈已空,若继续取数据,则会下溢,出现报错(栈空再取出现下溢)

以下以线性表为基础,图解说明各个操作

&注意:栈满,无法进行入栈,栈空,无法进行出栈以及获取栈顶元素(这是显而易见的)

代码:

  1. 定义栈的结构

//定义栈的结点结构

typedef struct StackNode {

    int value;

    struct StackNode* next;

}StackNode;



//定义栈的结构

typedef struct Stack {

    //定义此时栈顶元素位置(指针对应地址),每次入栈pos自增,再将相应元素入栈

StackNode* top;

    int size;

}Stack;

  1. 栈的初始化

/

/初始化栈

Stack* initStack() {

    Stack* stack = (Stack*)malloc(sizeof(Stack));

    stack->top = NULL;

    stack->size = 0;

    return stack;

}

//使用malloc函数分配大小为Stack的结构体大小的内存空间,将其转换为Stack类型的指针,将之赋值给变量stack,将首地址给stack->top,表示栈顶为空,最后将大小初始化为0,表示栈目前为空栈

创建一个空的栈结构,并且返回该栈的指针

  1. 判断此时栈是否为空
//判断栈是否为空

int isEmpty(Stack* stack) {

    return stack->top = NULL;

}

(非0为真,0为假)

  1. 入栈

/

//判断栈是否为空

int isEmpty(Stack* stack) {

    return stack->top = NULL;

}



//出栈

int pop(Stack* stack) {

    if (stack->top != NULL) {

         StackNode* node = stack->top;

         int value = node->value;

         stack->top = node->next;

         free(node);

         stack->size--;

         return value;

    }

    return -1;

}

入栈过程,图解:

  1. 出栈

考虑栈的大小,空栈不能出栈

//判断栈是否为空

int isEmpty(Stack* stack) {

    return stack->top = NULL;

}



//出栈

int pop(Stack* stack) {

    if (stack->top != NULL) {

         StackNode* node = stack->top;

         int value = node->value;

         stack->top = node->next;

         free(node);

         stack->size--;

         return value;

    }

    return -1;

}

出栈,图解:

  1. 获取栈顶元素

//获取栈顶元素

int topStack(Stack* stack) {

//判断是否为空

    if (stack->top != NULL) {

         return stack->top->value;

    }

//表示无法取栈顶元素

    return -1;

}

完整代码示例:(附代码运行效果)

#include<stdio.h>

#include<stdlib.h>



//栈的最大容量

#define STACK_SZ 100



//定义栈的结点结构

typedef struct StackNode {

    int value;

    struct StackNode* next;

}StackNode;



//定义栈的结构

typedef struct Stack {

    StackNode* top;

    int size;

}Stack;



//初始化栈

Stack* initStack() {

    Stack* stack = (Stack*)malloc(sizeof(Stack));

    stack->top = NULL;

    stack->size = 0;

    return stack;

}



//销毁栈

void destroy(Stack* stack) {

    while (stack->top != NULL) {

         StackNode* node = stack->top;

         stack->top = node->next;

         free(node);

    }

    free(stack);

}



//入栈

void push(Stack* stack, int value) {

    StackNode *node = (StackNode*)malloc(sizeof(StackNode));

    node->value = value;

    node->next = stack->top;

    stack->top = node;

    stack->size++;

}



//出栈

int pop(Stack* stack) {

    if (stack->top != NULL) {

         StackNode* node = stack->top;

         int value = node->value;

         stack->top = node->next;

         free(node);

         stack->size--;

         return value;

    }

    return -1;

}



//获取栈顶元素

int topStack(Stack* stack) {

    if (stack->top != NULL) {

         return stack->top->value;

    }

    return -1;

}



//判断栈是否为空

int isEmpty(Stack* stack) {

    return stack->top = NULL;

}



//判断栈是否满栈

int isFull(Stack* stack) {

    return stack->size = STACK_SZ;

}



//打印栈内容

void Print(Stack* stack) {

    StackNode* node = stack->top;

    while (node != NULL) {

         printf("%d", node->value);

         node = node->next;

    }

    printf("\n");

}



int main()

{

    Stack* stack = initStack();

    push(stack, 1);

    push(stack, 2);

    push(stack, 3);

    printf("栈顶元素:%d\n", topStack(stack));

    printf("出栈元素:%d\n", pop(stack));

    printf("栈顶元素:%d\n", topStack(stack));

    printf("是否为空:%d\n", isEmpty(stack));

    printf("是否满栈:%d\n", isFull(stack));

    Print(stack);

    destroy(stack);

    return 0;

}

代码运行效果:

代码注意:在 `main` 函数中,首先创建了一个栈,并向其中依次压入了 1、2、3 三个整数。然后,打印了栈顶元素、出栈元素、栈顶元素,并判断了栈是否为空和满。最后,打印了栈的内容,并销毁了栈。

需要注意的是,这个栈的实现是基于动态内存分配的,因此在使用完毕后需要调用 destroy 函数释放内存。

  1. 习题练习

题源:leetcode题库20题  有效的括号

思路:我们遍历给定的字符串 sss。当我们遇到一个左括号时,我们会期望在后续的遍历中,有一个相同类型的右括号将其闭合。由于后遇到的左括号要先闭合,因此我们可以将这个左括号放入栈顶。

当我们遇到一个右括号时,我们需要将一个相同类型的左括号闭合。此时,我们可以取出栈顶的左括号并判断它们是否是相同类型的括号。如果不是相同的类型,或者栈中并没有左括号,那么字符串 无效,返回 False

解决方法:

char pairs(char a) {
    if (a == '}') return '{';
    if (a == ']') return '[';
    if (a == ')') return '(';
    return 0;
}

bool isValid(char* s) {
    int len = strlen(s);
    //检查字符串长度,奇数直接return false
    if (len % 2 == 1) {
        return false;
    }
    int stk[len + 1], top = 0;
    //遍历字符串,然后压栈(左括号)
    for (int i = 0; i < len; i++) {
        char ch = pairs(s[i]);
        if (ch) {
            if (top == 0 || stk[top - 1] != ch) {
                return false;
            }
            top--;
        } else {
            stk[top++] = s[i];
        }
    }
    return top == 0;
}

测试用例:

时间复杂度:O(n),n是字符串s的长度

空间复杂度:O(n+6),6种括号,字符数量为O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值