C++实现堆栈

本文深入探讨了栈的三种主要存储结构:顺序栈、双堆栈和链栈。详细介绍了每种结构的特点、操作实现及应用场景,通过具体示例帮助读者理解不同栈结构的工作原理。

栈是一种操作受限的线性表。
栈的逻辑结构:插入和删除等操作只能发生在表的一端的特殊的线性表。
栈的物理结构:可以是顺序栈,也可以是链式栈,此外还有一种特殊的双堆栈。

一、顺序栈

顺序栈很大程度上就是个一维数组,只是规定对栈的操作只能在称为栈顶的一端进行。
顺序栈的类型定义通常如下:

/*顺序栈的类型定义*/
struct SeqStack{
    DataType data[MaxSize];
    int top;
};

定义的SeqStack类型由一个data[]数组和一个整型变量top构成,top用来表示当前栈顶元素的位置,也可称其为top指针,其值一般为≥-1的整数。
其结构图大致如下:
顺序栈的结构图
顺序栈的主要操作实现如下:
1.置空栈;初始化栈

void InitStack(SeqStack *s)
{
    s->top=-1;  //也可令top=0;
}

2.判断是否栈空

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

3.判断是否栈空

bool StackFull(SeqStack *s)
{
    return(s->top==MaxSize-1);
}

4.进栈:在栈顶存入值为x的元素

int Push(SeqStack *s,DataType x)
{
    if(StackFull(s))  //判断栈是否满溢
        return 0;
    s->data[++s->top]=x;
    return 1;
}

5.出栈:取栈顶元素

DataType Pop(SeqStack *s)
{
    if(StackEmpty(s)) //判断栈是否为空
        return 0;
    return(s->data[s->top--]);
}

一个完整的程序:

#include <iostream>
using namespace std;
#define MaxSize 100
typedef int DataType;

/*顺序栈的类型定义*/
struct SeqStack{
    DataType data[MaxSize];
    int top;
};

int main()
{
    void InitStack(SeqStack *s);
    bool StackEmpty(SeqStack *s);
    bool StackFull(SeqStack *s);
    int Push(SeqStack *s,DataType x);
    DataType Pop(SeqStack *s);

    SeqStack p,*s;
    s=&p;
    InitStack(s);          //初始化栈
    for(int i=0;i<=10;i++) //将0~10间的数值存入栈中
        Push(s,i);

    while(!StackEmpty(s)) //当栈为非空时弹出栈顶元素
        cout<<Pop(s)<<' ';
    cout<<endl;
    return 0;
}

/*初始化栈*/
void InitStack(SeqStack *s)
{
    s->top=-1;  //也可令top=0;
}

/*判断是否栈空*/
bool StackEmpty(SeqStack *s)
{
    return(s->top==-1);
}

/*判断是否栈满*/
bool StackFull(SeqStack *s)
{
    return(s->top==MaxSize-1);
}

/*在栈顶存入值为x的元素*/
int Push(SeqStack *s,DataType x)
{
    if(StackFull(s))  //判断栈是否满溢
        return 0;
    s->data[++s->top]=x;
    return 1;
}

/*退栈;取栈顶元素*/
DataType Pop(SeqStack *s)
{
    if(StackEmpty(s)) //判断栈是否为空
        return 0;
    return(s->data[s->top--]);
}

二、双堆栈

在同一个数组里实现两个堆栈的结构可将之称为双堆栈。为最大可能地利用数组空间,可使两个栈分别从数组的两头开始向中间生长,当两个栈的栈顶指针相遇时(RightTop-LeftTop==1),表示两个栈都满了。
双堆栈的结构图如下:
在这里插入图片描述
定义双堆栈的结构类型时,相较于顺序栈,只需多加一个表示第二个栈栈顶的指针即可,可作如下定义:

/*定义双堆栈结构*/
struct DStack
{
    ElementType data[MaxSize];
    int LeftTop;
    int RightTop;
};

在使用双堆栈时,可引入一个整型或布尔型的Tag变量,来只是是对左堆栈或右堆栈进行操作。
双堆栈的主要操作实现如下:
1.置空栈:初始化

void InitStack(DStack *s)
{
    s->LeftTop=-1;
    s->RightTop=MaxSize;
}

2.入栈:根据Tag值将元素x读入某一个栈的栈顶

void Push(DStack *s,ElementType x,int Tag)
{
    if(s->RightTop-s->LeftTop==1)
        cout<<"堆栈满"<<endl;
    else{
        if(Tag==1)
            s->data[++(s->LeftTop)]=x;
        else
            s->data[--(s->RightTop)]=x;
    }
}

3.退栈:根据Tag值读出某个栈的元素

ElementType Pop(DStack *s,int Tag)
{
    if(Tag==1){
        if(s->LeftTop==-1){
            cout<<"堆栈1空"<<endl;
            return 0;
        }
        else
            return(s->data[(s->LeftTop)--]);
    }
    else{
        if(s->RightTop==MaxSize){
            cout<<"堆栈2空"<<endl;
            return 0;
        }
        else
            return(s->data[(s->RightTop)++]);
    }
}

下面是一个将-10~10间的正整数存入数组左边,负整数存入数组右边,并将正负数交替输出的完整程序:

#include <iostream>
using namespace std;
#define MaxSize 20
typedef int ElementType;
/*定义双堆栈结构*/
struct DStack
{
    ElementType data[MaxSize];
    int LeftTop;
    int RightTop;
};


int main()
{
    void InitStack(DStack *s);
    void Push(DStack *s,ElementType x,int Tag);
    ElementType Pop(DStack *s,int Tag);

    DStack *s,Stack;
    s=&Stack;
    InitStack(s);
    for(int i=1;i<11;i++)  //将1~10间的整数存在数组的左边
        Push(s,i,1);
    for(int i=-1;i>-11;i--) //将-10~-1间的整数存在数组的右边
        Push(s,i,2);
    while(s->LeftTop!=-1 || s->RightTop!=MaxSize)
    { /*实现±1~±10之间的整数交替输出*/
        cout<<Pop(s,1)<<' ';
        cout<<Pop(s,2)<<' ';
    }
    cout<<endl;

    return 0;
}

/*初始化栈*/
void InitStack(DStack *s)
{
    s->LeftTop=-1;
    s->RightTop=MaxSize;
}

/*入栈:根据Tag值将元素x写入某个栈的栈顶*/
void Push(DStack *s,ElementType x,int Tag)
{
    if(s->RightTop-s->LeftTop==1)
        cout<<"堆栈满"<<endl;
    else{
        if(Tag==1)
            s->data[++(s->LeftTop)]=x;
        else
            s->data[--(s->RightTop)]=x;
    }
}

/*退栈:根据Tag值读出某个栈的栈顶元素*/
ElementType Pop(DStack *s,int Tag)
{
    if(Tag==1){
        if(s->LeftTop==-1){
            cout<<"堆栈1空"<<endl;
            return 0;
        }
        else
            return(s->data[(s->LeftTop)--]);
    }
    else{
        if(s->RightTop==MaxSize){
            cout<<"堆栈2空"<<endl;
            return 0;
        }
        else
            return(s->data[(s->RightTop)++]);
    }
}

程序运行结果如下:
在这里插入图片描述

三、链栈

链栈是栈的链式存储结构,它的运算是受限的单链表,插入和删除操作仅限制在表头位置上进行。像单链表一样,它也可添加一个数据域为空的头结点。
同顺序栈相比,链栈是可扩充的,它没有栈满的问题。
链栈的结构图如下:
链栈结构图
链栈的主要操作实现如下:
0.链栈的类型定义

typedef struct Node
{
    ElementType data;
    Node *next;
}LinkStack;

1.置空栈:初始化链栈

LinkStack *CreateStack()
{
    LinkStack *s;
    s=new LinkStack; /*s是堆栈的数据域为空的头结点*/
    s->next=NULL;
    return(s);
}

2.判断栈是否为空

/*判断链栈是否为空,返回值为布尔型*/
bool IsEmpty(LinkStack *s)
{
    return(s->next==NULL);
}

3.入栈

/*将元素x压入堆栈s的栈顶结点(紧跟头结点之后的那个结点)中*/
void Push(LinkStack *s,ElementType x)
{
    LinkStack *p;
    p=new LinkStack;
    p->data=x;
    p->next=s->next;
    s->next=p;
}

4.出栈

/*返回栈顶元素,并释放该元素对应的栈顶结点*/
ElementType Pop(LinkStack *s)
{
    LinkStack *top;
    ElementType x;

    if(IsEmpty(s)){
        cout<<"under flow"<<endl;
        return 0;
    }
    else{
        top=s->next;
        x=top->data;
        s->next=top->next;
        delete top;
        return(x);
    }
}

一个完整的程序:

#include <iostream>

using namespace std;
typedef int ElementType;

/*链栈的结点类型定义*/
typedef struct Node
{
    ElementType data;
    Node *next;
}LinkStack;

int main()
{
    LinkStack *CreateStack();
    bool IsEmpty(LinkStack *s);
    void Push(LinkStack *s,ElementType x);
    ElementType Pop(LinkStack *s);

    LinkStack *s;
    s=CreateStack();        //构建链栈s的头结点
    for(int i=1;i<=10;i++)  //依次将1~10间的数值作为栈顶元素压入堆栈中
        Push(s,i);

    while(!IsEmpty(s))     //依次弹出堆栈中的栈顶元素,直到堆栈为空
        cout<<Pop(s)<<' ';

    return 0;
}

/*构建一个链栈的头结点,返回该结点的指针*/
LinkStack *CreateStack()
{
    LinkStack *s;
    s=new LinkStack; /*s是堆栈的数据域为空的头结点*/
    s->next=NULL;
    return(s);
}

/*判断链栈是否为空,返回值为布尔型*/
bool IsEmpty(LinkStack *s)
{
    return(s->next==NULL);
}

/*将元素x压入堆栈s的栈顶结点(紧跟头结点之后的那个结点)中*/
void Push(LinkStack *s,ElementType x)
{
    LinkStack *p;
    p=new LinkStack;
    p->data=x;
    p->next=s->next;
    s->next=p;
}

/*返回栈顶元素,并释放该元素对应的栈顶结点*/
ElementType Pop(LinkStack *s)
{
    LinkStack *top;
    ElementType x;

    if(IsEmpty(s)){
        cout<<"under flow"<<endl;
        return 0;
    }
    else{
        top=s->next;
        x=top->data;
        s->next=top->next;
        delete top;
        return(x);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值