• C语言高级-4栈


    14天阅读挑战赛

    目录

    一、栈的原理

    1、栈的定义

    2、栈的应用

    (1)选课问题

    (2)旅游:怎么样把每个城市去且仅去一遍?

    (3)栈的使用场景

    (4)思考:栈为什么要有限制,后进先出?

    (5)栈的应用-表达式求值

    二、顺序栈

    1、顺序栈定义

    2、创建栈

    3、清空栈:

    4、判断栈是否空 

    5、判断栈是否满

    6、进栈 

    7、出栈 

    8、取栈顶元素

    9、释放

    10、定义测试函数

    三、链式栈原理及实现

    1、定义

    2、创建栈

    3、入栈

    4、出栈

    5、是否空栈

    6、取栈顶指针的值

    7、清空栈

    8、栈是否满

    9、释放栈内存


    一、栈的原理

    1、栈的定义

    • 栈是限制在一端进行插入操作和删除操作的线性表(俗称堆栈)
    • 允许进行操作的一端称为“栈顶”
    • 另一固定端称为“栈底”
    • 当栈中没有元素时称为“空栈”。
    • 特点 :后进先出(LIFO)。

    2、栈的应用

    (1)选课问题

    如上图,加入我们学习计算机课程,有些课程需要建立在先行课程基础上才能学习,那么我们该如何选择呢?

    上图中,我们发现,如果我们像学习一门课程,我们就需要把它放到栈底,然后找到它的前驱课程,然后一直类推找前驱课程,直到一个没有前驱课程的课程,就是栈顶,当我们学习完一门课程就是出栈,利用栈这个模型就解决了我们选课的问题。

    (2)旅游:怎么样把每个城市去且仅去一遍?

    选一个方向,到头后原路返回。再去访问另一个分支。

    如果用递归也可以解决,但是比较容易出错

    (3)栈的使用场景

    • 语法检查,符号成对出现。在我们日常编程中,括号都是成对出现的,比如“()”“[]”“{}”“<>”这些成对出现的符号。
    • 数制转换。比如100的八进制,100首先除以8商12余4,4首先进栈,然后12除以8商1余4,第二个余数4进栈接着1除以8,商0余1,第三个余数1进栈,最后将三个余数出栈,就得到了100的八进制数144。
    • 浏览器的前进后退

    (4)思考:栈为什么要有限制,后进先出?

    把一个非线性的问题,线性化。把前驱课程放在底入栈,没有之后再把其他课程放进去,一层一层转换为线性问题。

    (5)栈的应用-表达式求值

    • 建立操作数栈和运算符栈。运算符有优先级。
    • 自左至右扫描表达式,凡是遇到操作数一律进操作数栈。
    • 当遇到运算符时,如果它的优先级比运算符栈栈顶元素的优先级高就进栈。反之,取出栈顶运算符和操作数栈栈顶的连续两个操作数进行运算,并将结果存入操作数栈,然后继续比较该运算符与栈顶运算符的优先级。
    • 左括号一律进运算符栈,右括号一律不进运算符栈,取出运算符栈顶运算符和操作数栈顶的两个操作数进行运算,并将结果压入操作数栈,直到取出左括号为止。

     

    二、顺序栈

    1、顺序栈定义

    它是顺序表的一种,具有顺序表同样的存储结构,由数组定义,配合用数组下标表示的栈顶指针top(相对指针)完成各种操作。

    定义sqstack.h文件

    1. typedef  int  data_t ; /*定义栈中数据元素的数据类型*/
    2. typedef struct {        
    3.     data_t  *data ;  /*用指针指向栈的存储空间*/         如果用data[]数组,必须提前设定好数组长度,用指针可以让用户自定义
    4.     int  maxlen; /*当前栈的最大元素个数*/       
    5.     int  top ;  /*指示栈顶位置(数组下标)的变量*/  
    6. } sqstack;   /*顺序栈类型定义*/
    7. sqstack * stack_create(int len);
    8. int stack_push(sqstack * s, data_t value);
    9. int stack_empty(sqstack *s);
    10. int stack_full(sqstack *s);
    11. data_t stack_pop(sqstack *s);
    12. data_t stack_top(sqstack *s);
    13. int stack_clear(sqstack *s);
    14. int stack_free(sqstack *s);

    2、创建栈

    接下来实现sqstack.c

    1. sqstack * stack_create(int len) {
    2. sqstack * s;
    3. if ((s =(sqstack *)malloc(sizeof(sqstack))) == NULL) {
    4. printf("malloc sqstack failed\n");
    5. return NULL;
    6. }
    7. if ((s->data = (data_t *)malloc(len * sizeof(data_t)))==NULL) {
    8. printf("malloc data failed\n");
    9. free(s);
    10. return NULL;
    11. }
    12. memset(s->data, 0, len*sizeof(data_t));
    13. s->maxlen = len;
    14. s->top = -1;
    15. return s;
    16. }

    malloc,第一次是结构体,第二次是结构体里数据,用户传进来的值。

    3、清空栈:

    1. int stack_clear(sqstack *s) {
    2. if (s == NULL) {
    3. printf("s is NULL\n");
    4. return -1;
    5. }
    6. s->top = -1;
    7. return 0;
    8. }

    4、判断栈是否空 

    1. /*
    2. *@ret 1-empty
    3. * */
    4. int stack_empty(sqstack *s) {
    5. if (s == NULL) {
    6. printf("s is NULL\n");
    7. return -1;
    8. }
    9. return (s->top == -1 ? 1 : 0);
    10. }

    5、判断栈是否满

    1. /*
    2. * @ret 1-full
    3. * */
    4. int stack_full(sqstack *s) {
    5. if (s == NULL) {
    6. printf("s is NULL\n");
    7. return -1;
    8. }
    9. return (s->top == s->maxlen-1 ? 1 : 0);
    10. }

    6、进栈 

    1. int stack_push(sqstack * s, data_t value) {
    2. if (s == NULL) {
    3. printf("s is NULL\n");
    4. return -1;
    5. }
    6. if (s->top == s->maxlen-1) {
    7. printf("stack is full\n");
    8. return -1;
    9. }
    10. s->top++;
    11. s->data[s->top] = value;
    12. return 0;
    13. }

    7、出栈 

    1. data_t stack_pop(sqstack *s) {
    2. s->top--;
    3. return (s->data[s->top+1]);
    4. }

    8、取栈顶元素

    1. data_t stack_top(sqstack *s) {
    2. return (s->data[s->top]);
    3. }

    9、释放

    需要先释放后申请的空间,再去释放前面申请的空间

    1. int stack_free(sqstack *s) {
    2. if (s == NULL) {
    3. printf("s is NULL\n");
    4. return -1;
    5. }
    6. if (s->data != NULL)
    7. free(s->data);
    8. free(s);
    9. return 0;
    10. }

    10、定义测试函数

    1. #include
    2. #include "sqstack.h"
    3. int main(int argc, const char *argv[])
    4. {
    5. sqstack *s;
    6. s = stack_create(100);
    7. if (s == NULL)
    8. return -1;
    9. stack_push(s, 10); //入栈
    10. stack_push(s, 20);
    11. stack_push(s, 30);
    12. stack_push(s, 40);
    13. while (!stack_empty(s)) {
    14. printf("pop: %d \n", stack_pop(s) );
    15. }
    16. stack_free(s);
    17. return 0;
    18. }

    三、链式栈原理及实现

    1、定义

    插入操作和删除操作均在链表头部进行,链表尾部就是栈底,栈顶指针就是头指针。 

    1. typedef int data_t;
    2. typedef struct node {
    3. data_t data;
    4. struct node *next;
    5. }listnode, *linkstack;
    6. linkstack stack_create();
    7. int stack_push(linkstack s, data_t value);
    8. data_t stack_pop(linkstack s);
    9. int stack_empty(linkstack s);
    10. data_t stack_top(linkstack s);
    11. linkstack stack_free(linkstack s);

    2、创建栈

    接下来实现linkstack.c

    1. sqstack * stack_create(int len) {
    2. sqstack * s;
    3. if ((s =(sqstack *)malloc(sizeof(sqstack))) == NULL) {
    4. printf("malloc sqstack failed\n");
    5. return NULL;
    6. }
    7. if ((s->data = (data_t *)malloc(len * sizeof(data_t)))==NULL) {
    8. printf("malloc data failed\n");
    9. free(s);
    10. return NULL;
    11. }
    12. memset(s->data, 0, len*sizeof(data_t));
    13. s->maxlen = len;
    14. s->top = -1;
    15. return s;
    16. }

    3、入栈

    1. int stack_push(sqstack * s, data_t value) {
    2. if (s == NULL) {
    3. printf("s is NULL\n");
    4. return -1;
    5. }
    6. if (s->top == s->maxlen-1) {
    7. printf("stack is full\n");
    8. return -1;
    9. }
    10. s->top++;
    11. s->data[s->top] = value;
    12. return 0;
    13. }

    4、出栈

    1. data_t stack_pop(sqstack *s) {
    2. s->top--;
    3. return (s->data[s->top+1]);
    4. }

    5、是否空栈

    1. /*
    2. *@ret 1-empty
    3. * */
    4. int stack_empty(sqstack *s) {
    5. if (s == NULL) {
    6. printf("s is NULL\n");
    7. return -1;
    8. }
    9. return (s->top == -1 ? 1 : 0);
    10. }

    6、取栈顶指针的值

    1. data_t stack_top(sqstack *s) {
    2. return (s->data[s->top]);
    3. }

    7、清空栈

    1. int stack_clear(sqstack *s) {
    2. if (s == NULL) {
    3. printf("s is NULL\n");
    4. return -1;
    5. }
    6. s->top = -1;
    7. return 0;
    8. }

    8、栈是否满

    1. int stack_full(sqstack *s) {
    2. if (s == NULL) {
    3. printf("s is NULL\n");
    4. return -1;
    5. }
    6. return (s->top == s->maxlen-1 ? 1 : 0);
    7. }

    9、释放栈内存

    1. int stack_free(sqstack *s) {
    2. if (s == NULL) {
    3. printf("s is NULL\n");
    4. return -1;
    5. }
    6. if (s->data != NULL)
    7. free(s->data);
    8. free(s);
    9. return 0;
    10. }


     

  • 相关阅读:
    vue中实现签名画板
    【自然语言处理(NLP)】基于SQuAD的机器阅读理解
    (2022|NIPS,CogLM,分层,LoPAR,icetk)CogView2:通过分层 Transformer 更快更好地文本到图像生成
    cleanmyMac有必要吗,什么软件可以替代clean my mac
    Voice Control for ChatGPT简单高效的与ChatGPT进行交流学习。
    3、Kafka Broker
    Golang分布式应用之定时任务
    算法:(贪心算法)-独木舟问题
    SQL Server、MySQL主从搭建,EF Core读写分离代码实现
    C语言程序设计(三)高级特性
  • 原文地址:https://blog.csdn.net/m0_60718520/article/details/127577474