栈-基础知识(超详细)

参考资料:李春葆主编的数据结构教程第六版

栈(stack)的定义:

栈(又名:堆栈)是一种只能在一段进行插入或删除操作的线性表(受限的线性表)

栈的主要特点:先进后出/后进先出

基本概念:a.栈顶  (Top):(进出口)表中允许进行插入或删除操作的一端。

                    b.栈底 (Bottom):栈顶和栈底是相对而言的,一端被称作为栈顶,相对的,另一端就被称作为栈底。

                    c.进栈/入栈(Push):栈的插入操作。

                    d.出栈/退栈(Pop):栈的删除操作。

                    e.空栈:栈中没有元素/(s->Top==-1;)

                    f. 满栈:栈中已放满元素/(s->Top==MaxSize-1)

     判断出栈序列是否合法

在出栈结果中,任意选取一个位置i,该位置右边的所有小于位置i元素的,必须是降序序列。

eg:元素的进栈序列为12345,能否得到31425的出栈序列

任意选取=>若选31425中的第一个元素3,该位置右边的所有小于3的元素的序列为1 2,为升序,故得不到3142的出栈序列。(理解:若3被取出,且1和2两元素在3之后被取出,2被取出才能再取出2下面的1(1比2先进,所以要后出,满足栈先进后出的特点))。

n个不同元素通过一个栈产生的出栈序列的个数为C_{2n}^{n} /(n+1)(利用递归思想+卡特兰数)

 以n=4为例: 

栈的顺序存储结构及基本运算的实现

//声明顺序栈的类型

typedef struct {//顺序存储由数组和栈顶指针两部分组成
    int data[Maxsize];
    int top;
}Sqstack;

 //初始化栈

void InitStack(Sqstack *&s){
    s=(Sqstack *)malloc(sizeof(Sqstack));
    s->top=-1;//top(栈顶指针)指向-1时,为空栈,表明任何一个空间都没有被指向到
}

//销毁栈

void DestroyStack(Sqstack *&s){
    free(s);
}

//判断栈是否为空

bool StackEmpty(Sqstack *s){
    return (s->top==-1);
}

//进栈(push)

bool Push(Sqstack *&s,int e){
    //First 判断是否为满栈,若为满栈会出现上溢出现象,导致数据不能再入栈
    if(s->top==Maxsize-1)
        return false;
    else{
        s->data[++s->top]=e;
        return true;
    }
}

//退/出栈(pop)


​​​​​​​

bool Pop(Sqstack *&s,int &e){
    if(s->top==-1)
        return false;
    else{
        e=s->data[s->top--];
        return true;
    }
}

//取栈顶元素

bool GetTop(Sqstack *&s,int &e){
    if(s->top==-1)
        return false;
    else{
        e=s->data[s->top];
        return true;
    }
}

共享栈

1.栈空=>栈1为空栈的条件是top1==-1,栈2为空栈的条件是top==MaxSize;

2.栈满的条件=>top2-top1==1

3.入栈操作:栈1插入操作:s->data[++s->top1]=e;栈2插入操作:s->data[--top2]=e;

4.出栈操作:栈1删除操作:e=s->data[s->top--];栈2插入操作:e=s->data[top2++];

栈的链式存储结构及其基本运算的实现

采用链式存储结构的栈称为链栈。

//声明链栈的类型

typedef struct linknode{//每个节点由数据和指针两部分组成
    int data;
    struct linkNode *next;//指向结构体linknode的指针
}LinkStNode; //链栈结点类型

对于建立链表来说分为头插法和尾插法

头插法更为方便(top指针即为s->next[头结点]),若用尾插法则top指针在表尾,需要另外定义,且不易进行出栈操作,top指针需要指向出栈元素的上一个元素,但只有next指针,用双向链表就更为复杂。

//初始化栈
void InitStack(LinkStNode *&s){
    s=(LinkStNode *)malloc(sizeof(LinkStNode));
    s->next=NULL;// s->next即top指针指向为空
    
}
//销毁栈
void DestoryStsck(LinkStNode * &s){
    LinkStNode * pre=s, * p=s->next;
    while(p!=NULL){
        free(pre);
        pre=p;
        p=pre->next;
            }
    free(pre);
    }

 

//判断栈是否为空
bool StackEmpty(LinkStNode *s){
    return (s->next==NULL);
}
//进栈
bool Push(LinkStNode *&s,int e){//链栈不会出现上溢出的现象
    LinkStNode * p;
    p=(LinkStNode *)malloc(sizeof(LinkStNode));
    p->data=e;
    p->next=s->next;
    s->next=p;
    return true;
    }
//出栈-->一直出栈直至s->next==NUll就是销毁栈
bool Pop(LinkStNode *&s,int &e){
    LinkStNode *p=s->next;
    if(s->next==NULL)
        return false;//防止下溢出
    e=p->data;
    s->next=p->next;
    free(p);
    return true;
    
}

//取栈顶元素
bool GetTop(LinkStNode *s,int &e){
    if(s->next==NULL)
        return false;
    e=s->next->data;
    return true;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值