双栈(Dual Stack)

来源:互联网 发布:淘宝婚庆四件套 编辑:程序博客网 时间:2024/06/01 23:37

双栈(Dual Stack)

1. 双栈的概念

1.1 双栈的定义

  • 双栈是指两个顺序栈,是一种特殊的顺序栈。

1.2 双栈中各元素的逻辑及存储关系

  • 双栈共享一个地址连续的存储单元。即程序同时需要两个栈时,可以定义一个足够大的栈空间,该空间的两端分别设为两个栈的栈底,用bottom[0]=-1和bottom[1]=maxSize指示。
  • 压入数据时,让两个栈的栈顶top[0]和top[1]都向中间伸展,如果指示栈顶的指针top[0]+1等于另一个栈顶的指针top[1]时两栈已满。
  • 每次进栈时top[0]加1或top[1]减1,而退栈时top[0]减1或top[1]加1。
  • 如果top[0] == -1且top[1] == maxSize两栈为空。
  • 双栈的模型:
    这里写图片描述
  • 在双栈的情形下:
    (1)栈的初始化语句:bottom[0]=top[0]=-1,bottom[1]=top[1]=maxSize。
    (2)栈满的条件:top[0]+1 == top[1]。
    (3)栈空的条件:bottom[0]==top[0]==-1且bottom[1]==top[1]==maxSize。

2. 双栈的实现

2.1 双栈的类定义及其操作的实现

  • 文件:DualStack.h

    #ifndef DUAL_STACK_H_#define DUAL_STACK_H_#include <iostream>#include <string>#include <strstream>using namespace std;const int defaultSize = 50;         //默认栈空间大小const int stackIncreament = 20;     //栈溢出时扩展空间的增量const int n = 2;                    //设置n=2个栈共有一个栈空间template <class T>class DualStack{public:    DualStack(int sz = defaultSize);        //构造函数    ~DualStack();                           //析构函数public:    bool Push(const T& x, int d) ;      //新元素x进栈    bool Pop(T& x, int d);              //栈顶元素出栈,并将该元素的值保存至x    bool getTop(T& x, int d) const;     //读取栈顶元素,并将该元素的值保存至x    bool IsEmpty() const;               //判断栈是否为空    bool IsFull() const;                //判断栈是否为满    int getSize() const;                //计算栈中元素个数    void MakeEmpty();                   //清空栈的内容    void overflowProcess();             //栈的溢出处理public:    template <class T>    friend ostream& operator<<(ostream& os, const DualStack<T>& s); //输出栈中元素的重载操作<<private:    T *Vector;      //存放栈中元素的栈数组    int top[n];     //栈顶指针    int maxSize;    //栈最大可容纳元素个数};//构造函数template <class T>DualStack<T>::DualStack(int sz){    cout << "$ 执行构造函数" << endl;    if (sz >= 0)    {        maxSize = sz;                   top[0] = -1;        top[1] = maxSize;        Vector = new T[maxSize];    }}                       //析构函数template <class T>DualStack<T>::~DualStack(){    cout << "$ 执行析构函数" << endl;    delete[] Vector;    Vector = NULL;}   //新元素x进栈template <class T>bool DualStack<T>::Push(const T& x, int d){    if (true == IsFull())    {        return false;    }    if (0 == d)    {        top[0]++;    }    else    {        top[1]--;    }    Vector[top[d]] = x;    return true;}//栈顶元素出栈,并将该元素的值保存至xtemplate <class T>bool DualStack<T>::Pop(T& x, int d){    if (true == IsEmpty())    {        return false;    }    x = Vector[top[d]];    if (0 == d)    {        top[0]--;    }    else    {        top[1]++;    }    return true;}//读取栈顶元素,并将该元素的值保存至xtemplate <class T>bool DualStack<T>::getTop(T& x, int d) const{    if (true == IsEmpty())    {        return false;    }    x = Vector[top[d]];    return true;}//判断栈是否为空template <class T>bool DualStack<T>::IsEmpty() const{    return ((-1 == top[0]) && (maxSize == top[1])) ? true : false;}//判断栈是否为满template <class T>bool DualStack<T>::IsFull() const{    return (top[0] + 1 == top[1]) ? true : false;}//计算栈中元素个数template <class T>int DualStack<T>::getSize() const{    return (top[0] + 1) + (maxSize - top[1]);}//清空栈的内容template <class T>void DualStack<T>::MakeEmpty(){    delete[] Vector;    top[0] = -1;    top[1] = maxSize;    Vector = new T[maxSize];}//栈的溢出处理template <class T>void DualStack<T>::overflowProcess(){    int newSize = maxSize + stackIncreament;    T *neweVector = new T[newSize];    for (int i = 0; i <= top[0]; i++)    {        neweVector[i] = Vector[i];    }    for (int i = maxSize - 1; i >= top[1]; i--)    {        neweVector[i + stackIncreament] = Vector[i];    }    delete[] Vector;    Vector = neweVector;    maxSize = newSize;    top[1] += stackIncreament;}//输出栈中元素的重载操作<<template <class T>ostream& operator<<(ostream& os, const DualStack<T>& s){    os << "top[0]=" << s.top[0] << endl;    //输出栈1顶位置    for (int i = 0; i <= s.top[0]; i++)    {        os << "[" << i << "]" << " : " << s.Vector[i] << endl;    }    os << "top[1]=" << s.top[1] << endl;    //输出栈2顶位置    for (int i = s.maxSize - 1; i >= s.top[1]; i--)    {        os << "[" << i << "]" << " : " << s.Vector[i] << endl;    }    return os;}#endif /* DUAL_STACK_H_ */

2.2 主函数(main函数)的实现

  • 文件:main.cpp

    #include "DualStack.h"#define EXIT 0              //退出#define PUSH 1              //新元素x进栈#define POP  2              //栈顶元素出栈,并将该元素的值保存至x#define GETTOP 3            //读取栈顶元素,并将该元素的值保存至x#define ISEMPTY  4          //判断栈是否为空#define ISFULL 5            //判断栈是否为满#define GETSIZE 6           //计算栈中元素个数#define MAKEEMPTY 7         //清空栈的内容#define OPERATOR_OSTREAM 8  //输出栈中元素的重载操作<<#define OVERFLOWPROCESS 9   //栈的溢出处理void print_description(){    cout << "------------------------------>双栈<------------------------------" << endl;    cout << "功能选项说明:" << endl;    cout << "#0: 退出" << endl;    cout << "#1: 新元素x进栈" << endl;    cout << "#2: 栈顶元素出栈,并将该元素的值保存至x" << endl;    cout << "#3: 读取栈顶元素,并将该元素的值保存至x" << endl;    cout << "#4: 判断栈是否为空" << endl;    cout << "#5: 判断栈是否为满" << endl;    cout << "#6: 计算栈中元素个数" << endl;    cout << "#7: 清空栈的内容" << endl;    cout << "#8: 输出栈中元素的重载操作<<" << endl;    cout << "#9: 栈的溢出处理" << endl;    cout << "--------------------------------------------------------------------" << endl;}//判断输入的字符串每个字符是否都是数值0~9bool IsStackNumber(const string& s_num){    if (s_num.size() > 1)    {        return false;    }    if ((s_num[0] != '0') && (s_num[0] != '1'))    {        return false;    }    return true;}//判断输入的字符串每个字符是否都是数值0~9bool IsNumber(const string& s_num){    for (size_t i = 0; i < s_num.size(); i++)    {        if ((s_num[i] < '0') || (s_num[i] > '9'))        {            return false;        }    }    return true;}//类型转换——将string型转为模板类型Ttemplate <class T>T StrToTtype(const string& s_num){    T n_num;    strstream ss_num;    ss_num << s_num;    ss_num >> n_num;    return n_num;}//输入栈编号template <class T>int get_item(){    cout << "> 请输入栈编号,item = ";    string s_item;    cin >> s_item;    while (false == IsStackNumber(s_item))    {        cout << "* 输入有误,请重新输入:";        cin >> s_item;    }    return atoi(s_item.c_str());}//输入数据值template <class T>T get_data(){    cout << "> 请输入数据值,data = ";    string s_data;    cin >> s_data;    return StrToTtype<T>(s_data);}//输入数组的最大长度template <class T>int get_maxsize(){    cout << "> 请输入数组的最大长度,maxsize = ";    string s_maxsize;    cin >> s_maxsize;    while (false == IsNumber(s_maxsize))    {        cout << "* 输入有误,请重新输入:";        cin >> s_maxsize;    }    return atoi(s_maxsize.c_str());}//构造双栈template <class T>DualStack<T>* construct_dualstack(){    cout << "\n==> 创建双栈" << endl;    int n_maxsize = get_maxsize<T>();    DualStack<T> *dualStack = new DualStack<T>(n_maxsize);    return dualStack;}//析构双栈template <class T>void destory_seqstack(DualStack<T>* dualStack){    cout << "\n==> 释放双栈在堆中申请的空间,并将指向该空间的指针变量置为空" << endl;    delete dualStack;    dualStack = NULL;}//新元素x进栈template <class T>              void push(DualStack<T>* dualStack){    cout << "$ 执行新元素x进栈函数" << endl;    T data = get_data<T>();    int d = get_item<T>();    if (false == dualStack->Push(data, d))    {        cout << "* 进栈失败" << endl;        return;    }    cout << "* 进栈成功,data = " << data << endl;}//栈顶元素出栈,并将该元素的值保存至xtemplate <class T>  void pop(DualStack<T>* dualStack){    cout << "$ 执行栈顶元素出栈并将该元素的值保存至x函数" << endl;    T data;    int d = get_item<T>();    if (false == dualStack->Pop(data, d))    {        cout << "* 出栈失败" << endl;        return;    }    cout << "* 出栈成功,data = " << data << endl;}//读取栈顶元素,并将该元素的值保存至xtemplate <class T>  void gettop(DualStack<T>* dualStack){    cout << "$ 执行读取栈顶元素并将该元素的值保存至x函数" << endl;    T data;    int d = get_item<T>();    if (false == dualStack->getTop(data, d))    {        cout << "* 读取栈顶元素失败" << endl;        return;    }    cout << "* 读取栈顶元素成功,data = " << data << endl;}//判断栈是否为空template <class T>  void isempty(DualStack<T>* dualStack){    cout << "$ 执行判断栈是否为空函数,IsEmpty = " << dualStack->IsEmpty() << endl;}//判断栈是否为满template <class T>  void isfull(DualStack<T>* dualStack){    cout << "$ 执行判断栈是否为满函数,IsFull = " << dualStack->IsFull() << endl;}//计算栈中元素个数template <class T>  void getsize(DualStack<T>* dualStack){    cout << "$ 执行计算栈中元素个数函数,Size = " << dualStack->getSize() << endl;}//清空栈的内容template <class T>  void makeempty(DualStack<T>* dualStack){    cout << "$ 执行清空栈的内容函数" << endl;    dualStack->MakeEmpty();}//输出栈中元素的重载操作<<template <class T>  void operator_ostream(DualStack<T>* dualStack){    cout << "$ 执行输出栈中元素的重载操作<<函数" << endl;    cout << *dualStack;//或operator<<(cout, *dualStack);}//栈的溢出处理template <class T>void overflowprocess(DualStack<T>* dualStack){    cout << "$ 执行栈的溢出处理函数" << endl;    dualStack->overflowProcess();}//双栈操作选择template <class T>void select_operation(DualStack<T>* dualStack){    if (NULL == dualStack)    {        cout << "* 没有构造双栈,请先构造双栈。" << endl;        return;    }    string s_operation;    while (s_operation != "0")    {        cout << "\n==> 请输入功能选项编号(按\"0\"退出程序):";        cin >> s_operation;        while (false == IsNumber(s_operation))        {            cout << "* 输入有误,请重新输入:";            cin >> s_operation;        }        int n_operation = atoi(s_operation.c_str());        switch (n_operation)        {            case EXIT://退出            {                cout << "$ 退出程序" << endl;                break;            }            case PUSH://新元素x进栈            {                push(dualStack);                break;            }            case POP://栈顶元素出栈,并将该元素的值保存至x            {                pop(dualStack);                break;            }            case GETTOP://读取栈顶元素,并将该元素的值保存至x            {                gettop(dualStack);                break;            }            case ISEMPTY://判断栈是否为空            {                isempty(dualStack);                break;            }            case ISFULL://判断栈是否为满            {                isfull(dualStack);                break;            }            case GETSIZE://计算栈中元素个数            {                getsize(dualStack);                break;            }            case MAKEEMPTY://清空栈的内容            {                makeempty(dualStack);                break;            }            case OPERATOR_OSTREAM://输出栈中元素的重载操作<<            {                operator_ostream(dualStack);                break;            }            case OVERFLOWPROCESS://栈的溢出处理            {                overflowprocess(dualStack);                break;            }            default:            {                cout << "* 请输入正确的功能选项编号" << endl;                break;            }        }    }}int main(int argc, char* argv[]){    print_description();    DualStack<int> *dualStack = construct_dualstack<int>();    select_operation(dualStack);    destory_seqstack(dualStack);    system("pause");    return 0;}

3. 双栈的优缺点

3.1 优点

  • 两栈的大小不是固定不变的,在实际运算过程中,一个栈有可能进栈元素多而体积大些,另一个则可能小些。
  • 两个栈共用一个栈空间,相互调剂,灵活性强。

3.2 缺点

  • 运算较为复杂。
  • 长度为定值,中途不易扩充。
  • 注:n(n>2)个栈的情况更有所不同,采用多个栈共享栈空间的顺序存储表示方式,处理十分复杂,在插入时元素的移动量很大,因而时间代价较高。特别是当整个存储空间即将充满时,这个问题更加严重。
  • 解决上述问题的办法就是采用链接方式作为栈的存储表示方式。

3.3 双栈的适用情况

  • 当栈满时要发生溢出,为了避免这种情况,需要为栈设立一个足够大的空间。但如果空间设置得过大,而栈中实际只有几个元素,也是一种空间浪费。此外,程序中往往同时存在几个栈,因为各个栈所需的空间在运行中是动态变化着的。如果给几个栈分配同样大小的空间,可能实际运行时,有的栈膨胀得快,很快就产生了溢出,而其他的栈可能此时还有许多空闲空间。这时就可以利用双栈,两个栈共用一个栈空间,相互调剂,灵活性强。

参考文献:
[1]《数据结构(用面向对象方法与C++语言描述)(第2版)》殷人昆——第三章
[2]《C/C++常用算法手册》秦姣华、向旭宇——第二章
[3] 百度搜索关键字:双栈

2 0
原创粉丝点击