栈和队列之经典(下)

(4)判断元素出栈、入栈顺序的合法性。如:入栈的序列(1,2,3,4,5),出栈序列为(4,5,3,2,1)是合法序列,入栈的序列(1,2,3,4,5),出栈序列为(1,5,3,2,4)是不合法序列 。

对于有关栈的问题,建立辅助栈解决会是很不错的选择。在本题中把输入的入栈序列的数字依次压入该辅助栈,并按照出栈序列依次从该栈中弹出数字。
规律:如果下一个弹出的数字刚好是栈顶数字,那么直接弹出;如果下一个弹出的数字不在栈顶,则把压栈序列中还没有入栈的数字压入辅助栈,直到把下一个需要弹出的数字压入栈顶为止;如果所有数字都压入栈中后依然没有找到下一个弹出的数字,那么该序列不可能是一个合法的弹出序列。

bool Ispoporder(int *stack_in,int *stack_out,int len_in,int len_out)
{
    assert(stack_in&&stack_out);
    if(len_in != len_out)//排除入栈序列和出栈序列长度不相等的情况
      return false;

    stack<int> s;//建立辅助栈
    int i = 0;
    int j = 0;
    for(; i<len_in;++i)
    {
        s.push(stack_in[i]);
        while((s.top()==stack_out[j]) && s.size()>0)
        {
            s.pop();
            ++j;
        }
    }
    if(s.size()==0)
        return true;
    else
        return false;
}
int main()
{
    int stack_in[] = {1,2,3,4,5};
    int stack_out[] = { 4,5,3,2,1 };//出栈序列合法
    int stack_out[] = { 4,5,2,3,1};//出栈序列不合法
    int len_in = sizeof(stack_in)/sizeof(stack_in[0]);
    int len_out = sizeof(stack_out)/sizeof(stack_out[0]);
    bool ret = Ispoporder(stack_in,stack_out,len_in,len_out);
    if(ret)
        cout<<"出栈序列合法"<<endl;
    else
        cout<<"出栈序列不合法"<<endl;
    return 0;
}

对于弹出序列为4 5 3 2 1的合法调用过程:
这里写图片描述
对于弹出序列4 5 2 3 1的不合法情况:
这里写图片描述

(5)一个数组实现两个栈
通常用一个数组实现两个栈有三种办法
方法1.分奇偶位压栈
数组的奇数位放栈1的数据,数组的偶数位放栈2的数据。
这里写图片描述
方法2.自中间向两边压栈
将数组从中间一分为二,栈1从中间向左依次压栈,栈2从中间向右依次压栈。
这里写图片描述
方法3.自两边向中间压栈
这里写图片描述
综上比较,对于方法一和方法二,若两个栈所压入元素多少不同,其中一个栈压入很少的元素时,就会造成空间资源浪费。当任何一个栈的元素到达数组的数组尾部或者起始位置时,则开始扩容。
而方法三便可以避免上述空间浪费问题,当一个栈的元素被pop掉后,另一个栈可以占用该位置,因此资源利用率较高。

接下来我们实现自两边向中间压栈的方案:

class ArrayTwoStack
{
public:
    ArrayTwoStack()
        :_a(new int[2])
        , _capacity(2)
        ,stack1_size(0)
        ,stack2_size(1)
    {}

    void Stack1Push(const int& x)//压栈
    {
        CheckCapacity();
        _a[stack1_size++] = x;
    }

    void Stack2Push(const int& x)
    {
        CheckCapacity();
        _a[stack2_size--] = x;
    }

    void Stack1Pop()//出栈
    {
        if (stack1_size > 0)
            stack1_size--;
    }

    void Stack2Pop()
    {
        if (stack2_size < _capacity - 1)
            stack2_size++;  
    }

    const int& Stack1Top()
    {
        if (stack1_size != 0)
            return _a[stack1_size-1];
    }

    const int& Stack2Top()
    {
        if(stack2_size != _capacity-1)
            return _a[stack2_size+1];
    }

    size_t SizeofStack1()
    {
        return stack1_size;
    }

    size_t SizeofStack2()
    {
        return _capacity - 1 - stack2_size;
    }

    void Stack1Print()
    {
        for (int i = 0; i < stack1_size; i++)
        {
            cout << _a[i] << " ";
        }
        cout << endl;
    }

    void Stack2Print()
    {
        for (int i =stack2_size+1; i < _capacity; i++)
        {
            cout << _a[i] << " " ;
        }
        cout << endl;
    }

protected:
    void CheckCapacity()
    {
        if (stack2_size - stack1_size > 0)
            return;
        else//扩容
        {
            int newCapacity = _capacity * 2;
            int* tmp = new int[newCapacity];
            for (int i = 0; i < stack1_size; i++)
                tmp[i] = _a[i];

            int stack2_index = newCapacity - 1;
            for (int i = _capacity - 1; i > stack2_size; i--)
                tmp[stack2_index--] = _a[i];

            _a = tmp;
            _capacity = newCapacity;
            stack2_size = stack2_index;
        }
    }

private:
    int* _a;
    int _capacity;  
    int stack1_size; //栈顶下标
    int stack2_size;  
};
int main()
{
    ArrayTwoStack a1;
    a1.Stack1Push(1);
    a1.Stack1Push(2);
    a1.Stack1Push(3);

    a1.Stack2Push(4);
    a1.Stack2Push(5);
    a1.Stack1Print();
    a1.Stack2Print();
    return 0;
}

这里写图片描述
增容情况:
这里写图片描述

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zjx624bjh/article/details/78815943
文章标签: 栈和队列 数组
个人分类: 面试题
想对作者说点什么? 我来说一句

栈和队列习题

2014年03月30日 135KB 下载

没有更多推荐了,返回首页

不良信息举报

栈和队列之经典(下)

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭