自学内容网 自学内容网

C语言数据结构——详细讲解《栈》


前言

  • 在 C 语言编程中,数据结构是非常重要的一部分,它能够帮助我们更高效地组织和处理数据。
  • 今天,我们就来详细讲解一下其中的栈数据结构

一、栈的概念

  • “栈” 在计算机中是一种数据结构,是一种特殊的线性表
  • 它只允许在固定的一端进行插入删除元素操作
  • 进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。

在这里插入图片描述

  • 栈中的数据元素遵守后进先出的原则

在这里插入图片描述

  • 压栈(进栈、入栈):栈的插入操作叫做进栈(压栈、入栈),入数据在栈顶
  • 出栈:栈的删除操作叫做出栈,出数据也在栈顶

二、栈的定义

  • 栈的结构通常由一个数组链表来实现。
  • 数组实现中,栈顶通常由一个变量来指向,这个变量记录了栈顶元素的索引。每次入栈操作会增加这个索引,每次出栈操作会减小这个索引。
  • 链表实现中,栈顶是链表的头节点,入栈操作相当于在链表头部插入一个新节点,出栈操作相当于删除链表的头节点。
下面我们来详细讲一下栈的链式结构
  • 首先,我们要定义栈的数据结构
typedef struct Stack 
{
    int* arr;
    int top;
    int capacity;
} Stack;
  • arr指栈中的元素
  • top指栈顶
  • capacity表示栈的容量

三、栈的操作

1.初始化栈

  • 有了栈的结构体定义,我们需要对栈进行初始化
void initStack(Stack* ps) 
{
    ps->capacity = 4;
    ps->top = 0;
    ps->arr = (int*)malloc(ps->capacity * sizeof(int));
    assert(ps->arr!= NULL);
}
  • 首先,把栈的初始容量设置为 4
  • 然后,将栈顶top设置为 0,表示此时栈是空的
  • 接着,使用malloc函数来动态分配内存,以便能够存储栈的元素

2. 入栈操作

栈初始化好了之后,接下来就往栈里放元素

void push(Stack* ps, int x) {
    if (ps->top == ps->capacity) 
    {
        // 栈满,扩容
        int newCapacity = ps->capacity == 0? 4 : 2 * ps->capacity;
        int* tmp = (int*)realloc(ps->arr, newCapacity * sizeof(int));
        if (tmp == NULL) {
            perror("realloc fail\n");
            exit(1);
        }
        ps->arr = tmp;
        ps->capacity = newCapacity;
    }
    ps->arr[ps->top++] = x;
}

这个函数就是用来把一个元素x压入栈中的

  • 首先,检查一下栈是否已满了 ps->top == ps->capacity
  • 如果栈满了,就得进行扩容操作
int newCapacity = ps->capacity == 0? 4 : 2 * ps->capacity;

如果当前栈的容量是 0 ,就把新容量设为 4;要是当前容量不为 0,就是当前容量的两倍

int* tmp = (int*)realloc(ps->arr, newCapacity * sizeof(int));

然后使用realloc函数来重新分配内存

  • 最后,把元素x放到arr[top]这个位置上,然后再把top加 1,这样就表示栈顶元素的位置更新

3. 出栈操作

int pop(Stack* ps) 
{
    assert(ps->top > 0);
    return ps->arr[--ps->top];
}
  • 把top减 1,再返回arr[top]的值,这个值就是栈顶元素

4. 获取栈顶元素

int top(Stack* ps) 
{
    assert(ps->top > 0);
    return ps->arr[ps->top - 1];
}

如果栈不为空,那就返回arr[top - 1]的值,这个值就是栈顶元素的值

5. 检查栈是否为空

int isEmpty(Stack* ps) 
{
    return ps->top == 0;
}

如果top等于 0,那就说明栈是空的,这时候函数就会返回 1;要是top不等于 0,那就说明栈里还有元素,函数就会返回 0

6.释放栈内存

void freeStack(Stack* ps) 
{
    free(ps->arr);
    ps->arr = NULL;
    ps->top = 0;
    ps->capacity = 0;
}
以上便是栈的全部操作,下面给大家带来一道栈的例题,应用一下所学的知识

四、栈的例题

在这里插入图片描述
链接地址》》》》》》有效括号

  • 大家先思考一下怎么做
    在这里插入图片描述
    题目讲解
  • 思路,将左括号看为入栈,右括号看为出栈
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

// 定义栈的数据结构
typedef struct Stack {
    int* arr;
    int top;
    int capacity;
} Stack;

// 初始化栈
void initStack(Stack* ps) {
    ps->capacity = 4;
    ps->top = 0;
    ps->arr = (int*)malloc(ps->capacity * sizeof(int));
    assert(ps->arr!= NULL);
}

// 入栈操作
void push(Stack* ps, int x) {
    if (ps->top == ps->capacity) {
        // 栈满,扩容
        int newCapacity = ps->capacity == 0? 4 : 2 * ps->capacity;
        int* tmp = (int*)realloc(ps->arr, newCapacity * sizeof(int));
        if (tmp == NULL) {
            perror("realloc fail\n");
            exit(1);
        }
        ps->arr = tmp;
        ps->capacity = newCapacity;
    }
    ps->arr[ps->top++] = x;
}

// 出栈操作
int pop(Stack* ps) {
    assert(ps->top > 0);
    return ps->arr[--ps->top];
}

// 获取栈顶元素
int top(Stack* ps) {
    assert(ps->top > 0);
    return ps->arr[ps->top - 1];
}

// 检查栈是否为空
int isEmpty(Stack* ps) {
    return ps->top == 0;
}

// 释放栈内存
void freeStack(Stack* ps) {
    free(ps->arr);
    ps->arr = NULL;
    ps->top = 0;
    ps->capacity = 0;
}

bool isValid(char* s) {
    Stack st;
    initStack(&st);
    char* pi = s;
    while (*pi!= '\0') {
        if (*pi == '(' || *pi == '{' || *pi == '[') {
            // 入栈
            push(&st, *pi);
        } else {
            // 判断,取栈
            if (isEmpty(&st)) {
                freeStack(&st);
                return false;
            }
            char top = (char)pop(&st);
            if ((top == '(' && *pi!= ')') || (top == '[' && *pi!= ']') || (top == '{' && *pi!= '}')) {
                freeStack(&st);
                return false;
            }
        }
        pi++;
    }
    bool ret = isEmpty(&st);
    freeStack(&st);
    return ret;
}
下面详细讲解一下,对比上面代码增加的部分
bool isValid(char* s) {
    Stack st;//定义了一个名为st的Stack类型的变量,用于辅助判断括号的有效性
    initStack(&st);//调用initStack函数对栈st进行初始化
    char* pi = s;
    while (*pi!= '\0') {
        if (*pi == '(' || *pi == '{' || *pi == '[') {
            // 入栈
            push(&st, *pi);
        } else {
            // 判断,取栈
            if (isEmpty(&st)) {
                freeStack(&st);
                return false;
            }
            char top = (char)pop(&st);
            if ((top == '(' && *pi!= ')') || (top == '[' && *pi!= ']') || (top == '{' && *pi!= '}')) {
                freeStack(&st);
                return false;
            }
        }
        pi++;
    }
    bool ret = isEmpty(&st);
    freeStack(&st);
    return ret;
}
  • 首先定义了一个字符指针pi,并将其初始化为指向传入的字符串s的首地址。这个指针将用于遍历字符串s。
  • 接着循环遍历栈中的元素
  • 如果等于左括号则入栈
  • 然后调用push函数将该左括号字符压入栈st中
  • 如果pi所指向的字符不是左括号
  • 首先检查栈st是否为空
  • 如果栈不为空,调用pop函数从栈st中弹出栈顶元素,并将其转换为char类型后赋值给变量top
  • 如果不匹配,则调用freeStack函数释放栈的内存

bool ret = isEmpty(&st);
当遍历完整个字符串s后,检查栈st是否为空。如果栈为空,说明所有的左括号都找到了对应的右括号,将true赋值给ret;否则,将false赋值给ret

  • 最后返回ret的值

五、本文的所有代码

Stack.c

#include "Stack.h"
int main() {
    Stack myStack;
    initStack(&myStack);

    // 入栈几个数据实例
    push(&myStack, 10);
    push(&myStack, 20);
    push(&myStack, 30);

    // 获取栈顶元素并打印
    printf("当前栈顶元素: %d\n", top(&myStack));

    // 出栈操作并打印出栈元素
    printf("出栈元素: %d\n", pop(&myStack));

    // 再次获取栈顶元素并打印
    printf("当前栈顶元素: %d\n", top(&myStack));

    // 检查栈是否为空并打印结果
    if (isEmpty(&myStack)) {
        printf("栈为空\n");
    }
    else {
        printf("栈不为空\n");
    }

    // 释放栈内存
    freeStack(&myStack);

    return 0;
}

Stack,h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

// 定义栈的数据结构
typedef struct Stack {
    int* arr;
    int top;
    int capacity;
} Stack;

// 初始化栈
void initStack(Stack* ps) {
    ps->capacity = 4;
    ps->top = 0;
    ps->arr = (int*)malloc(ps->capacity * sizeof(int));
    assert(ps->arr != NULL);
}

// 入栈操作
void push(Stack* ps, int x) {
    if (ps->top == ps->capacity) {
        // 栈满,扩容
        int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
        int* tmp = (int*)realloc(ps->arr, newCapacity * sizeof(int));
        if (tmp == NULL) {
            perror("realloc fail\n");
            exit(1);
        }
        ps->arr = tmp;
        ps->capacity = newCapacity;
    }
    ps->arr[ps->top++] = x;
}

// 出栈操作
int pop(Stack* ps) {
    assert(ps->top > 0);
    return ps->arr[--ps->top];
}

// 获取栈顶元素
int top(Stack* ps) {
    assert(ps->top > 0);
    return ps->arr[ps->top - 1];
}

// 检查栈是否为空
int isEmpty(Stack* ps) {
    return ps->top == 0;
}

// 释放栈内存
void freeStack(Stack* ps) {
    free(ps->arr);
    ps->arr = NULL;
    ps->top = 0;
    ps->capacity = 0;
}

最后一题代码

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

// 定义栈的数据结构
typedef struct Stack {
    int* arr;
    int top;
    int capacity;
} Stack;

// 初始化栈
void initStack(Stack* ps) {
    ps->capacity = 4;
    ps->top = 0;
    ps->arr = (int*)malloc(ps->capacity * sizeof(int));
    assert(ps->arr!= NULL);
}

// 入栈操作
void push(Stack* ps, int x) {
    if (ps->top == ps->capacity) {
        // 栈满,扩容
        int newCapacity = ps->capacity == 0? 4 : 2 * ps->capacity;
        int* tmp = (int*)realloc(ps->arr, newCapacity * sizeof(int));
        if (tmp == NULL) {
            perror("realloc fail\n");
            exit(1);
        }
        ps->arr = tmp;
        ps->capacity = newCapacity;
    }
    ps->arr[ps->top++] = x;
}

// 出栈操作
int pop(Stack* ps) {
    assert(ps->top > 0);
    return ps->arr[--ps->top];
}

// 获取栈顶元素
int top(Stack* ps) {
    assert(ps->top > 0);
    return ps->arr[ps->top - 1];
}

// 检查栈是否为空
int isEmpty(Stack* ps) {
    return ps->top == 0;
}

// 释放栈内存
void freeStack(Stack* ps) {
    free(ps->arr);
    ps->arr = NULL;
    ps->top = 0;
    ps->capacity = 0;
}

bool isValid(char* s) {
    Stack st;
    initStack(&st);
    char* pi = s;
    while (*pi!= '\0') {
        if (*pi == '(' || *pi == '{' || *pi == '[') {
            // 入栈
            push(&st, *pi);
        } else {
            // 判断,取栈
            if (isEmpty(&st)) {
                freeStack(&st);
                return false;
            }
            char top = (char)pop(&st);
            if ((top == '(' && *pi!= ')') || (top == '[' && *pi!= ']') || (top == '{' && *pi!= '}')) {
                freeStack(&st);
                return false;
            }
        }
        pi++;
    }
    bool ret = isEmpty(&st);
    freeStack(&st);
    return ret;
}
非常感谢您的阅读,喜欢的话记得三连哦

在这里插入图片描述


原文地址:https://blog.csdn.net/2402_83322742/article/details/144052060

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!