栈的定义

栈:限定在表尾进行插入和删除操作的线性表。类似于弹夹。允许插入和删除的一端为栈顶(top),另一端为栈底(bottom)。栈又称为后进先出LIFO(Last In First Out)的线性表。另外栈也可以用一维数组或链表的形式来完成。堆栈的另外一个相对的操作方式称为队列(FIFO)。
[维基-栈](https://zh.wikipedia.org/wiki/%E5%A0%86%E6%A0%88

栈的基本特点:
  1. 先入后出,后入先出。
  2. 除头尾节点之外,每个元素有一个前驱,一个后继。

栈的抽象数据类型

理论上来数,线性表的操作特性它都具备的

InitStack(*S): 初始化建立一个空栈。
Empty(*S):判空操作。若S为空表,则返回true,否则返回false。
DestroyStack(*S):销毁操作。销毁栈,并释放栈所占用的内存空间。
ClearStack(*S): 将栈清空
GetTop(S, *e): 若栈存在非空,用e返回S的栈顶元素。
Push(*S, e): 若栈S存在插入新元素e到栈中并称为栈顶元素。
pop(*S, e): 删除栈中栈顶元素,并用e返回其值。
Length(S):求栈长度。返回栈的长度,即栈S中数据元素的个数。

栈的存储结构

栈的顺序存储结构

栈是线性表的特列,那么栈的顺序存储结构可以是线性表顺序存储的简化,简称为顺序栈。那么我们可以使用数组来表示栈,下标为0的一端作为栈底,定义一个top变量来指示栈顶元素在数组中的位置。 空栈,top = -1;两个元素,top = 1;满栈,top = stacksize-1(数组的最后一个元素)。

在执行Push操作 pop操作时,要注意是否越界,返回相应的错误信息。

两栈共享空间

栈的顺序存储很方便,但是在使用的时候要确定数组的大小,对于用来存放此消彼长的数据元素的两个栈,可以采用一个数组存储两个栈。

让两个栈的栈底分别在数组的两端,两个栈的元素分别从数组的两端向中间靠拢。栈1空时top1 = -1,栈2空时top2 = stacksize;而当两个栈顶指针相差为1时,即 top1 + 1 == top2。两栈共享空间的情况一般用于两个栈的空间需求有相反关系的时候。 Pop/Push操作需要判断stacknumber,溢出条件有两top变量重合和相应的空栈条件。

栈的链式存储结构

用链表的形式表示栈,简称为链栈。由于单链表需要头指针,而栈需要栈顶指针,所以栈顶一般放在单链表的头部,也就不需要头结点了。

链栈基本不存在栈满的情况,除非内存已经用光了;栈空为top=NULL 。链栈的进栈操作就是将新元素作为头指针,原链表作为直接后继链接上即可;而出栈操作和很简单,获得头指针元素值,将栈顶指针向下移一位,然后释放原来的头结点。

如果栈的使用过程中元素的变化时是不可预料的,最好使用链栈;如果元素的变化在可控范围之内,使用顺序栈会比较好一点。

栈的应用

  1. 递归:直接或间接调用自己的函数,定义中必须有一个满足时递归不再进行的条件。eg:求斐波那契数列。
    在一般的程序中使用递归函数,会因为语言的不同有不同的效果,比如python的程序栈就很浅,只有几千,不适合大型递归程序。
  2. 后缀表达式求四则运算(没有括号的四则运算) 规则:从左到右遍历每个数字和符号,如果遇到数字就进栈,遇到符合就将两个数字出栈运算,将结果进栈,一直到获得结果。
  3. 中缀转后缀:从左到右遍历每个数字和符号,遇到数字就输出;遇到符号就判断与栈顶元素的优先级(乘除高于加减),符号为右括号或者优先级低就将栈内元素依次输出然后进栈,若优先级高就直接进栈。一直到输出全部数字和符号。

顺序栈和链表栈的实现

顺序栈
/*
   顺序栈基本操作
*/
#include <stdio.h>
#include <stdlib.h>
//定义栈中最大元素的个数.
#define MAXNUM 20
typedef int DataType;
typedef struct SeqStack{
    int t; //栈顶位置指示
    DataType s[MAXNUM];
}SeqStack,*PSeqStack;

//创建一个空栈;为栈结构申请空间.并将栈顶元素变量赋值为-1
PSeqStack createEmptyStack(void);
//判断pastack所指的栈是否为空,当pastack所指的栈为空时返回1;否者为0.
int isEmptyStack(PSeqStack pastack);
//压栈操作
void push_seq(PSeqStack pastack,DataType e);
//出栈操作
void pop_seq(PSeqStack pastack);
//pastack不为空栈时,求栈顶元素
DataType getTop_seq(PSeqStack pastack);

//初始化栈
PSeqStack createEmptyStack(){
    PSeqStack pastack=(PSeqStack)malloc(sizeof(struct SeqStack));
    if (pastack==NULL)
    {
        printf("Error:out of space\n");
    }else{
        pastack->t=-1;
    }

    return pastack;
}

//判断栈是否为空
int isEmptyStack(PSeqStack pastack){
    return pastack->t==-1;
}

//入栈操作
void push_seq(PSeqStack pastack,DataType e){
    if(pastack->t>=MAXNUM-1){
        printf("Stack Overflow!\n");
    }else{
        pastack->t++;
        pastack->s[pastack->t]=e;
    }
}

//出栈操作
void  pop_seq(PSeqStack pastack){
    if (pastack->t==-1)
    {
        printf("UnderFlow!\n");
    }else{
        printf("Pop:%d\n",pastack->s[pastack->t]); 
        pastack->t--;
    }
}

//返回栈顶元素
DataType getTop_seq(PSeqStack pastack){

     return pastack->s[pastack->t];
}

int main(){
    PSeqStack stack1=createEmptyStack();
    push_seq(stack1,1);
    push_seq(stack1,2);
    push_seq(stack1,3);
    printf("%d\n",getTop_seq(stack1));
    pop_seq(stack1);
    pop_seq(stack1);
    pop_seq(stack1);

    return 0;
}
链表栈
#include <stdio.h>
#include <stdlib.h>

typedef int DataType;
struct Node;
typedef struct Node *PNode;

struct Node
{
     DataType info;
     PNode link;

};

struct LinkStack
{
    PNode top;
};
typedef struct LinkStack *PLinkStack;

// 申请链栈结构空间,创建一个空链栈,返回指向空链接的指针.
PLinkStack createEmptyStack_link(void);
// 链式栈是否为空栈
int isEmptyStack_link(PLinkStack plstack);
//入栈
void push(PLinkStack plstack, DataType e);
//出栈
void pop(PLinkStack plstack);
//对非空栈求栈顶元素

//初始化栈
PLinkStack createEmptyStack_link(){
    PLinkStack plstack=(PLinkStack)malloc(sizeof(struct LinkStack));
    if (plstack==NULL)
    {
        printf("Out of space\n");
    }else{
        plstack->top=NULL;
    }

    return plstack;
}

//判断栈是否为空
int isEmptyStack_link(PLinkStack plstack){
   return plstack->top==NULL;
}

//入栈操作
void push(PLinkStack plstack,DataType e){
    PNode newnode=(PNode)malloc(sizeof(struct Node));
    if(newnode==NULL){
      printf("Out of space.\n");
    }else{
      newnode->info=e;
      newnode->link=plstack->top;
      plstack->top=newnode;
    }
}

//出栈操作
void pop(PLinkStack plstack){
    if (isEmptyStack_link(plstack))
    {
        printf("Empty Stack pop.\n");
    }else{
        PNode p=plstack->top;
        printf("%d\n",p->info);
        plstack->top=plstack->top->link;
        free(p);
    }
}

int main(){
    PLinkStack plstack1=createEmptyStack_link();
    push(plstack1,1);
    push(plstack1,3);
    push(plstack1,5);
    pop(plstack1);
    pop(plstack1);
    pop(plstack1);
    pop(plstack1);
}
内容概要:本文介绍了奕斯伟科技集团基于RISC-V架构开发的EAM2011芯片及其应用研究。EAM2011是一款高性能实时控制芯片,支持160MHz主频和AI算法,符合汽车电子AEC-Q100 Grade 2和ASIL-B安全标准。文章详细描述了芯片的关键特性、配套软件开发套件(SDK)和集成开发环境(IDE),以及基于该芯片的ESWINEBP3901开发板的硬件资源和接口配置。文中提供了详细的代码示例,涵盖时钟配置、GPIO控制、ADC采样、CAN通信、PWM输出及RTOS任务创建等功能实现。此外,还介绍了硬件申领流程、技术资料获取渠道及开发建议,帮助开发者高效启动基于EAM2011芯片的开发工作。 适合人群:具备嵌入式系统开发经验的研发人员,特别是对RISC-V架构感兴趣的工程师和技术爱好者。 使用场景及目标:①了解EAM2011芯片的特性和应用场景,如智能汽车、智能家居和工业控制;②掌握基于EAM2011芯片的开发板和芯片的硬件资源和接口配置;③学习如何实现基本的外设驱动,如GPIO、ADC、CAN、PWM等;④通过RTOS任务创建示例,理解多任务处理和实时系统的实现。 其他说明:开发者可以根据实际需求扩展这些基础功能。建议优先掌握《EAM2011参考手册》中的关键外设寄存器配置方法,这对底层驱动开发至关重要。同时,注意硬件申领的时效性和替代方案,确保开发工作的顺利进行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值