一文学会栈的原理,有代码实现(源代码可运行)

栈(stack)又称为堆栈,是一种操作受限的线性表,拥有和线性表相同的逻辑结构。栈的限制只能在表的一端进行插入和删除操作,向一个栈新增一个元素叫进栈,让他称为栈顶元素。从一个栈删除元素叫出栈,使得下面的元素成为新的栈顶元素。
栈可以用单链表的操作一样,只是操作的时候只允许在一端操作,也申请一个头节点,如下,一个空栈,空栈的条件是head->next==NULL;
在这里插入图片描述

栈的操作只能在上面一头进行。
若入栈1,2,3,4, 5,如图::
入栈1,栈顶为1:
在这里插入图片描述
入栈2,栈顶为2:
在这里插入图片描述
入栈3,栈顶为3:
在这里插入图片描述

入栈4,栈顶为4:在这里插入图片描述

入栈5,栈顶为5:
在这里插入图片描述
出栈的顺序是相反的:5–>4–>3–>2–>1。

相关源代码

mystack.h:

/**********************************
*Copyright(C),2010-2020,programer
*Filename:mystack.h
*Author:programer-L
*Description:stack some operator function
*Date:2020年8月12日
*Version: v1.0
**********************************/

#ifndef _MYSTACK_H_
#define _MYSTACK_H_


#define SUCCESS  0 
#define ERROR -1 

typedef int ElemType;

typedef struct stack_node {
    int data;
    struct stack_node *next;
}*PtrToNode;

typedef PtrToNode Stack;


/**********************************
*Function:create_stack
*Description:创建一个栈
*Input:
*Output:
*Return: 栈节点
*Others:
**********************************/
Stack create_stack();

/**********************************
*Function:push_stack
*Description:压栈
*Input:
*Output:
*Return: 
*Others:
**********************************/
int push_stack(Stack s, int data);

/**********************************
*Function:pop_stack
*Description:出栈
*Input:
*Output:
*Return: 
*Others:
**********************************/
int pop_stack(Stack s);

/**********************************
*Function:top_stack
*Description:取栈顶元素
*Input:
*Output:
*Return: 
*Others:
**********************************/
int top_stack(Stack s);

/**********************************
*Function:show_stack
*Description:输出栈里元素
*Input:
*Output:
*Return: 
*Others:
**********************************/
void show_stack(Stack s);

/**********************************
*Function:stack_is_empty
*Description:判断栈是否为空
*Input:
*Output:
*Return: 
*Others:
**********************************/
int stack_is_empty(Stack s);

/**********************************
*Function:get_stack_num
*Description:获取栈元素个数
*Input:
*Output:
*Return: 
*Others:
**********************************/
int get_stack_num(Stack s);

/**********************************
*Function:destory_stack
*Description:销毁栈
*Input:
*Output:
*Return: 
*Others:
**********************************/
int destory_stack(Stack s);

#endif

mystack.c:


#include <stddef.h>
#include "mystack.h"

/* 创建一个空栈 */
Stack create_stack()
{
    Stack S;

    S = (Stack)malloc(sizeof(struct stack_node));
    if (NULL == S)
    {
        printf("malloc fair!\n");
        return NULL;
    }

    S->next = NULL;

    return S;
}

/* PUSH 操作 */
int push_stack(Stack s,int data) 
{
    // 新建一个结点,用于存放压入栈内的元素,即新的栈顶
    PtrToNode head_node = (PtrToNode)malloc(sizeof(struct stack_node));
    if (head_node == NULL)
    {
         printf("malloc fair!\n");
         return  ERROR;
    }

    //类似于链表的头插法
    head_node->data = data;            // 添加数据
    head_node->next = s->next;        // 新的栈顶 head_node 的 next 指针指向原来的栈顶 s->next
    s->next = head_node;            // s->next 现在指向新的栈顶

    return SUCCESS;
}

/* POP 操作 */
int pop_stack(Stack s) 
{
    PtrToNode head_node = (PtrToNode)malloc(sizeof(struct stack_node));
    if (head_node == NULL)
    {
        printf("malloc fair!\n");
        return ERROR;
    }

    // 先判断栈是否为空,若栈为空,则不能再进行出栈操作,报错
    if (stack_is_empty(s)) 
    {
        printf("Error! Stack is empty!\n");
    }
    else 
    {
        head_node = s->next;            // head_node 为栈顶
        s->next = head_node->next;        // s->next 指向 head_node->next ,即新的栈顶
        free(head_node);                // 释放原来栈顶元素所占的内存
    }
    
    return SUCCESS;
}


/* 销毁栈 */
int destory_stack(Stack s)
{
    Stack curnode;
    for(; s!=NULL; )
    {
        curnode = s;
        s = s->next;
        free(curnode);
    }

    return SUCCESS;
}

/* 获取栈元素个数 */
int get_stack_num(Stack s)
{
    int len = 0;
    for(Stack curnode=s->next; curnode!=NULL; curnode=curnode->next)
    {
        len++;
    }
    printf("栈的个数是:%d\n", len);

    return len;
}

/* 输出栈里元素 */
void show_stack(Stack s)
{
    printf("stack elem is:");
    for(Stack curnode=s->next; curnode!=NULL; curnode=curnode->next)
    {
        printf("%d ", curnode->data);
    }

    printf("\n");
}

/* 查看栈顶元素 */
int top_stack(Stack s) 
{
    if (stack_is_empty(s)) 
    {
        printf("Error! Stack is empty!\n");
        return ERROR;
    }
    else 
    {
        return s->next->data;
    }
}

/* 判断栈是否为空 */
int stack_is_empty(Stack s) 
{
    return NULL == s->next;
}

main.c:

#include <stdio.h>
#include "mystack.h"

int main() 
{
    Stack stack = create_stack();        // 新建一个空栈
    int top_data,i;
    // 压栈操作,执行10次
    for (i = 0;i < 10;i++) {
        push_stack(stack, i);
    }

    show_stack(stack);
    // 出栈操作,执行1次
    pop_stack(stack);
    // 返回栈顶元素的值
    top_data = top_stack(stack);
    printf("%d\n", top_data);

    get_stack_num(stack);

    destory_stack(stack);

    return 0;
}

运行结果结果:

root@ubuntu:~/myvscode/list/stack# ./mystack
stack elem is:9 8 7 6 5 4 3 2 1 0
8
栈的个数是:9

栈的应用

栈的应用十分广泛 ,在函数调用、中断处理、表达式求值、内存分配等操作中都需要用到栈。
假设有一个函数 f(),现在函数 f() 要调用函数 g() ,而函数 g() 又需要调用函数 h() 。当函数 f() 开始调用函数 g() 时,函数 f() 的所有局部变量需要由系统存储起来,否则被调用的新函数 g() 将会覆盖调用函数 f() 的变量;不仅如此,主调函数当前的位置也是需要保存的,以便被调函数执行完后知道回到哪里接着执行调用函数。同样的,函数 g() 调用函数 h() 时,g() 的相关信息也需要存储起来。在函数 h() 执行完成后,再从系统中取出函数 g() 的相关信息接着执行函数 g();当函数 g() 执行完成后,从系统中取出函数 f() 的相关信息然后接着执行函数 f()。从这里的描述中可以看到,函数调用时,调用函数的信息是存放在一个后进先出结构中的,显然,用栈来存放再好不过,用一幅图演示一下。

在这里插入图片描述

也可关注微信公众号,欢迎交流。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值