美文网首页
栈的相关知识与代码实现

栈的相关知识与代码实现

作者: 曲谐_ | 来源:发表于2017-07-16 12:34 被阅读0次

一、栈的相关知识

栈的定义:

是限定仅在表尾进行插入和删除操作的线性表。
我们把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的栈称为空栈。栈又称为后进先出(Last In First Out,LIFO)的线性表。

理解栈的定义需要注意:

  • 首先他是一个线性表,元素具有线性关系,即前驱后继关系。
  • 这里的表尾指的是栈定而不是栈底。
  • 栈的插入操作叫做进栈,或者压栈,入栈。栈的删除动作叫做出栈,也叫弹栈。

进栈出栈变化形式:

问题:最先进栈的元素,是不是就只能最后出栈呢?
答:不一定。因为没有对栈内元素出入时间做限制。在不是所有元素都进栈的情况下,事先进去的元素也可以出栈,只要保证是栈顶元素即可。
举例:有三个数字1,2,3依次进栈,有哪些出栈次序呢?

  • 第一种:1,2,3进,3,2,1出。
  • 第二种:1进,1出,2进,2出,3进,3出。即1,2,3出。
  • 第三种:1,2进,2出,1出,3进,3出。即2,1,3出。
  • 第四种:1进,1,2,3进,3出,2出。即1,3,2出。
  • 第五种:1,2进,2出,3进,3出,1出。即2,3,1出。
  • 不可能为3,1,2出。因为3进,1,2必然进。2在1上面,因此如果3出了,必先出2。

栈的顺序存储结构

  • 顺序线性表用数组可以实现,下标为0作为栈底。
  • 定义一个top变量来指示栈顶元素在数组中的位置。StackSize为存储栈的长度。因此栈顶位置top必须小徐StackSize。
  • 当栈存在一个元素时,top等于0,空栈时top=-1。

两栈共享空间

提出思路:因为有的时候对于两个栈,类型相同,而其中一个利用率不高,另一个却有快溢出迹象的时候,可以将两个栈共享使用,使得利用率提高。
做法:数组有两个端点,两个栈有两个栈底,让一个栈底下标为0,另一个栈底为数组的末端,即下标为n-1。这样两个栈增加元素就是两端点向中间延伸
由此可见,top1和top2是栈1和栈2的栈顶指针,只要它们俩不见面,两个栈就可以一直使用。
栈1为空时,top1=-1,栈2位空时,top2=n
问题:什么时候栈满?
:想想极端情况。

  • 若栈2是空栈,栈1的top1=n-1时,栈1满了。反之,当栈1为空栈,top2=0时,为栈2满。
  • 但更多的情况,其实就是两个栈见面之时,也就是两个指针相差为1——top1+1=top2为栈满。

使用条件:通常是两个栈的空间需求有相反关系,也即一个栈增长另一个栈缩短。像买股票一样,一个人买入一定有一个你不知道的人在卖出。有人赚钱,另一个人就赔钱。

栈的链式存储结构

  • 规定栈顶放在单链表的头部。
  • 链栈的好处是不用过多考虑栈满的情况,除非内存已经没有可以使用的空间。如果真的发生,那此时计算机操作系统已经面临死机崩溃的情况,而不是这个链栈是否溢出的问题了。
  • 对于空栈来说,链表原定义是头指针指向空,那么链栈的空其实就是top==NULL的时候。

二、代码实现

顺序栈的代码实现

//SeqStack.h
#ifndef SEQSTACK_H_
#define SEQSTACK_H_
const int StackSize = 40;
class SeqStack
{
private:
    int top;
    int num[StackSize];
public:
    SeqStack();
    ~SeqStack();
    void Push(int e);
    void Pop();
    bool isempty();
    bool isfull();
    void clear();
    void Print();
};
#endif

头文件SeqStack.h,包含了入栈出栈判断里面是否是满的以及清空等功能。
这个栈存储了一个int数组。

#include<iostream>
#include"SeqStack.h"
using std::cout;
using std::endl;
SeqStack::SeqStack():top(-1){}
SeqStack::~SeqStack(){}
void SeqStack::Push(int e)
{
    if(isfull())
    {
        cout << "Stack is Full!Push failed." << endl;
        return;
    }
    num[++top] = e;
}
void SeqStack::Pop()
{
    if(isempty())
    {
        cout << "Stack is Empty!Pop failed." << endl;
        return;
    }
    top--;
}
bool SeqStack::isempty()
{
    if(top == -1)
    {
        cout << "Stack is empty!" << endl;
        return true;
    }
    return false;
}
bool SeqStack::isfull()
{
    if(top == StackSize - 1)
    {
        cout << "Stack is full!" << endl;
        return true;
    }
    return false;
}
void SeqStack::clear()
{
    if(isempty())
        cout << "SeqStack is already empty!" << endl;
    while(top!=-1)
    {
        Pop();
        top--;
    }
}
void SeqStack::Print()
{
    if(isempty())
        cout << "No elements printed." << endl;
    for(int i=0;i<top;i++)
        cout << num[i] << " ";
    cout << endl;
}

函数实现SeqStack.cpp,可以自己建立一个简单的程序验证一下,这里不再赘述。

链栈的代码实现

//LinkStack.h
#ifndef LINKSTACK_H_
#define LINKSTACK_H_
class LinkStack
{
private:
    struct StackNode
    {
        int num;//存储数据
        StackNode * next;//next指针
    };
    StackNode * top;
    int length;
public:
    LinkStack();
    ~LinkStack();
    void Push(int e);
    void Pop();
    bool isempty();
    void clear();
    void Print();
};
#endif

链栈头文件,存储变量和方法。

//LinkStack.cpp
#include<iostream>
#include"LinkStack.h"
using std::cout;
using std::endl;
LinkStack::LinkStack()
{
    top = NULL;
    length = 0;
}
LinkStack::~LinkStack()
{
}
void LinkStack::Push(int e)
{
    StackNode * p = new StackNode;
    p->num=e;
    p->next=top;
    top=p;
    length++;
}
void LinkStack::Pop()
{
    StackNode * p = new StackNode;
    if(top == NULL)
    {
        cout << "The LinkStack is empty!Cannot pop!" << endl;
        return;
    }
    p=top;
    top=top->next;
    delete p;
    length--;
}
void LinkStack::clear()
{
    while(top)
    {
        StackNode * temp = top;
        top = top->next;
        delete temp;
        length--;
    }
}
void LinkStack::Print()
{
    if(top == NULL)
    {
        cout << "No elements!" << endl;
        return;
    }
    StackNode * temp = top;
    while(temp)
    {
        cout << temp->num << " ";
        temp = temp->next;
    }
    cout << endl;
}

相关文章

  • 栈的相关知识与代码实现

    一、栈的相关知识 栈的定义: 是限定仅在表尾进行插入和删除操作的线性表。我们把允许插入和删除的一端称为栈顶(top...

  • Swift 队列&栈 相关操作

    栈 LIFO(后进先出) 队列 FIFO(先进先出) 队列与栈相互的实现 栈 - 队列实现 队列 - 栈实现 相关...

  • 队列的相关知识与代码实现

    一、队列的相关概念和定义 试想一下,有的时候电脑像死机一样,鼠标点什么都没用。而过了一会却好像酒醒了一样把你刚才的...

  • 栈和队列

    本文章只针对知识进行概括性梳理,相关代码详情可以咕咕哥 栈的引入模型:手枪子弹的压堂(出栈),装子弹(进栈),递归...

  • Java 栈和队列的使用(转)

    在java中要实现栈和队列,需要用到java集合的相关知识,特别是Stack、LinkedList等相关集合类型。...

  • 2019-08-04-使用俩个队列/栈实现一个栈/队列

    1,问题:使用俩个队列实现一个栈 代码实现 调用方式 2,使用俩个栈实现一个队列 代码实现 调用方式

  • iOS 如何返回到上上层控制器

    直接上代码 相关知识点:1)导航控制器(UINavigationController)是以栈的形式存放子控制器的,...

  • 栈抽象数据类型及实现

    栈的思维导图 代码实现

  • 1. 面试题整理

    代码题1. 代码:数组、字符串、链表问题 2. 代码:栈与队列、树与图3. 代码:C库函数实现4. 代码:华为面试...

  • 数据结构-栈

    栈的特点 先进后出 栈的相关操作都是通过栈顶位置进行相关操作的 栈的接口抽象 栈可以通过线性表直接实现(链表、数组...

网友评论

      本文标题:栈的相关知识与代码实现

      本文链接:https://www.haomeiwen.com/subject/snaahxtx.html