ACM -栈(1)

栈——计算机术语

栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。

1>栈是一种线性存储结构,

1.先进后出,即“FILO”;
2.只可在表尾即栈顶进行插入(压入PUSH)和删除(弹出POP)操作。
3.分为顺序栈链式栈

顺序栈:基于数组的栈;以数组为底层数据结构时,通常以数组头为栈底,数组头到数组尾为栈顶的生长方向;
链式栈:基于链表的栈;以链表为底层的数据结构时,以链表头为栈顶,便于节点的插入与删除,压栈产生的新节点将一直出现在链表的头部;

2>栈的相关概念:

1.栈顶栈底;
2.入栈出栈(压栈弹栈);

3>栈的常用操作:

1.bool isEmpty();//判断是否空;
2.sqStack(); &~sqStack();//建栈;
3.void push();//压栈;
4.int pop();//出栈;
5.int getTop();//获取栈顶元素的值;
6.void display();//遍历栈中元素;
7.求栈的大小;
……

栈的应用举例

1)数制转换
2)括号匹配的检验
3)行编辑程序
4)迷宫求解
5)表达式求值
6)栈与递归的实现

4>实例分析

使用标准库的栈时, 应包含相关头文件,在栈中应包含头文件: #include< stack > 。定义:stack< int > s;

s.empty();         //如果栈为空则返回true, 否则返回false;
s.size();          //返回栈中元素的个数
s.top();           //返回栈顶元素, 但不删除该元素
s.pop();           //弹出栈顶元素, 但不返回其值
s.push();          //将元素压入栈顶

碰到一个很有意思的链式栈实现:(CSDN BLOG,非原创)

#include <iostream>
using namespace std;
struct  SqStack
{
    char data;
    SqStack* next;
};
bool StackEmpty(SqStack* s)
{
    return(s->next==NULL);
}
void Push(SqStack*& s,char& e)
{
    SqStack *p=new SqStack;
    p->data=e;
    p->next=s->next;
    s->next=p;

}
bool Pop(SqStack*& s,char& e)
{
    SqStack* p;
    if(s->next==NULL)
        return false;
    p=s->next;
    e=p->data;
    s->next=p->next;
    delete p;
    return true;
}
bool GetTop(SqStack* s,char& e)
{
    if(s->next==NULL)
        return false;
    e=s->next->data;
    return true;
}
void DestroyStack(SqStack*& s)
{
    SqStack *p=s,*q=s->next;
    while(q!=NULL)
    {
        delete p;
        p=q;
        q=p->next;
    }
}
int main()
{
    SqStack *L=new SqStack;
    L->next=NULL;
    char e[5]= {'a','b','c','d','e'};
    for(int i=0; i<5; ++i)
    {
        Push(L,e[i]);
    }
    int i=0;
    SqStack *p=L;
    while((p=p->next)!=NULL)
    {
        ++i;
    }
    cout<<"栈的长度为:"<<i<<endl;
    SqStack *q=L;
    while((q=q->next)!=NULL)
    {
        cout<<q->data;
    }
    cout<<endl;
    char a;
    while(Pop(L,a))
        cout<<a;
    cout<<endl;
    if(StackEmpty(L))
        cout<<"空栈。\n";
    else
        cout<<"非空栈。\n";
    DestroyStack(L);
    return 0;
}

这个代码可爱的地方在于,他的整个函数设计是根据main函数实现的,他把SqStack *L一开始就设置为:L->next=NULL;
这就相当于在L内人为地设置了一个看不见的first,first没有data,只有next,颠覆了以往将L=NULL直接设置的传统(虽说是数据结构的知识,但是这么做的还是绕了我一大圈,汗。
注意这个代码的特殊性吧。他在除main函数之外的其他函数里并没设置这样的东西,所以在函数定义语句里很杂糅,但是结果却是对的的原因。)

5>实敲分析

顺序栈实敲练习:(有参考代码,参考百度百科-栈)

#include <iostream>
//顺序栈
using namespace std;

struct sqStack{
    enum{MaxSize = 100};
    int data[MaxSize];
    int top;
    sqStack();
    ~sqStack();
    bool isEmpty();
    void push(int x);
    int pop();
    int getTop();
    void display();
};

sqStack :: sqStack()
{
    top = -1;
}

sqStack :: ~sqStack(){}

bool sqStack :: isEmpty()
{
    return (top == -1);
}

void sqStack :: push(int x)
{
    if(top ==MaxSize - 1)
        cout << "栈溢出" << endl;
    else
    {
        top++;
        data[top] = x;
    }
}

int sqStack :: pop()
{
    if(top == -1)
        cout << "栈已空" << endl;
    else
    {
        return data[top--];
    }
}

int sqStack :: getTop()
{
    if(top == -1)
    {
        cout << "栈空" << endl;
        return 0;
    }
    else
    {
        return data[top];
    }
}

void sqStack :: display()
{
    int tmp = top;
    while(tmp!=-1)
    {

        cout << data[tmp] << endl;
        tmp--;
    }
}
int main()
{
    sqStack st;
    cout << "栈空:" << st.isEmpty() << endl;
    for(int i = 1;i < 10; i ++)
    {
        st.push(i);
    }
    st.display();
    cout << "退栈"<< endl;
    st.pop();
    cout << "栈顶元素" << st.getTop()<< endl;
    st.pop();
    st.display();
    return 0;
}

链式栈实敲练习:

#include <iostream>
//链式栈:Linked Stack;
using namespace std;

struct sqStack{
    char data;
    struct sqStack * next;
};

bool stackEmpty(sqStack *s)
{
    return (s->next == NULL);
}

void push(sqStack *&s,char &e)//入栈
{
    sqStack * p = new sqStack;
    p->data = e;
    p->next = s->next;
    s->next = p;
}

bool pop(sqStack *&s,char &e)//出栈
{
    if(stackEmpty(s))
        return false;
    sqStack * p;
    p = s->next;
    e = p->data;
    s->next = p->next;//标星星,很重要。编写的时候还写错了!
    delete p;
    return true;
}

bool getTop(sqStack *s,char &e)
{
    if(stackEmpty(s))
        return false;
    e = s->next->data;
    return true;
}

void destoryStack(sqStack *&s)
{
    sqStack * p = s;
    sqStack * q = s->next;
    while(q != NULL)
    {
        delete p;
        p = q;
        q = p->next;
    }
}

int main()
{
    sqStack *L = new sqStack;
    L->next = NULL;
    char e[5]={'a','b','c','d','e'};
    for(int i = 0;i < 5; i++)
    {
        push(L,e[i]);
    }
    int i = 0;
    sqStack *p = L;
    while ((p = p->next)!= NULL)
    {
        ++i;
    }
    cout << "栈的长度为" << i << endl;
    sqStack *q = L;
    while((q = q->next)!= NULL)
    {
        cout << q->data;
    }
    cout << endl;
    char a;
    while (pop(L,a))
        cout << a;
    cout << endl;
    if(stackEmpty(L))
        cout << "空栈" << endl;
    else
        cout << "非空栈" << endl;
    destoryStack(L);
    return 0;
}

把上面的实例稍稍改一下,嘿嘿,就是我们常见的啦:(结果当然是一样的~)

#include <iostream>
//链式栈:Linked Stack;
using namespace std;

struct sqStack{
    char data;
    struct sqStack * next;
};

bool stackEmpty(sqStack *s)
{
    return (s == NULL);
}

void push(sqStack *&s,char &e)//入栈
//如果不是void,返回push后的栈,则应写为:sqStack * push(sqStack *s,char & e)
{
    sqStack * p = new sqStack;
    p->data = e;
    p->next = s;
    s = p;
}

bool pop(sqStack *&s,char &e)//出栈
//如果不是void,返回pop后的栈,则应写为:sqStack * pop(sqStack *s,char & e)
{
    if(stackEmpty(s))
        return false;
    sqStack * p;
    p = s;
    e = p->data;
    s = p->next;//
    delete p;
    return true;
}

bool getTop(sqStack *s,char &e)
{
    if(stackEmpty(s))
        return false;
    e = s->data;
    return true;
}

void destoryStack(sqStack *&s)
{
    sqStack * p = s;
    sqStack * q = s->next;
    while(q != NULL)
    {
        delete p;
        p = q;
        q = p->next;
    }
}

int main()
{
    sqStack *L = new sqStack;
    L = NULL;
    char e[5]={'a','b','c','d','e'};
    for(int i = 0;i < 5; i++)
    {
        push(L,e[i]);
    }
    int i = 0;
    sqStack *p = L;
    while (p != NULL)
    {
        ++i;
        p = p->next;
    }
    cout << "栈的长度为" << i << endl;
    sqStack *q = L;
    while(q != NULL)
    {
        cout << q->data;
        q = q->next;
    }
    cout << endl;
    char a;
    while (pop(L,a))
        cout << a;
    cout << endl;
    if(stackEmpty(L))
        cout << "空栈" << endl;
    else
        cout << "非空栈" << endl;
    destoryStack(L);
    return 0;
}

6>总结

(以上均为c++语言编写)
1.链式栈的优点在于它能够克服用数组实现的顺序栈空间利用率不高的问题,但是需要Wie每个栈元素分配额外的指针空间来存放指针域。
2.链式栈以Node(节点)形式存储,可以动态申请内存,比静态内存的顺序栈好了不知多少。
3.栈具有记忆功能,对栈的插入与删除操作中,不需改变栈底指针。
4.栈(Stack)可用多种语言实现!其我们编写语言就是栈这种逻辑结构的物理实现
5.以上大部分参考https://blog.csdn.net/zichen_ziqi/article/details/80807989,少部分参考百度百科关于栈的定义与其他csdnblog。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值