栈和队列之经典(下)

原创 2017年12月15日 18:57:02

(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;
}

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

算法入门经典之栈和队列篇

做对的事情比把事情做对重要 /** *@author StormMaybin *@Date 2016-07-17 */ 最近一段时间会对数据结构的知识和算法基础进行总结,尽量一天一更!如果时间错不...
  • StromMaybin
  • StromMaybin
  • 2016年07月17日 01:55
  • 1487

易经中的经典名句

1、天行健,君子以自强不息。《乾·象》2、居上位而不骄,在下位而不忧。故乾乾因其时而惕,虽危而无咎矣。《乾·文言》3、同声相应,同气相求。水流湿,火就燥,云从龙,风从虎,各从其类也。《乾·文言》4、地...
  • striker
  • striker
  • 2011年06月29日 11:50
  • 4375

寒假第三天--栈和队列--数据结构实验之栈四:括号匹配 (栈)

数据结构实验之栈四:括号匹配 Time Limit: 1000MS Memory limit: 65536K 题目描述  给你一串字符,不超过50个字符,可能包括括号、数字、字母...
  • u013015642
  • u013015642
  • 2014年01月16日 19:02
  • 1587

数据结构与算法(C++版):表、栈和队列

前言本系列博客为学习数据结构与算法过程中的原创笔记,其中代码实现基于C++语言。STL中的向量和表在C++语言的库中包含有公共数据结构的实现,这就是众所周知的标准模版库(Standard Templa...
  • u013271326
  • u013271326
  • 2017年06月06日 11:37
  • 243

栈和队列之经典(上篇)

要完成下面关于栈和队列的题目,首先要明白 栈的特性:后进先出 队列的特性:先进先出 (1)实现一个栈,要求实现Push(入栈)、Pop(出栈)、Min(返回最小值的操作)的时间复杂度为O(...
  • zjx624bjh
  • zjx624bjh
  • 2017年12月11日 17:11
  • 31

浅析数据结构与算法1--栈和队列

1. 基本概念 概念很简单,栈 (Stack)是一种后进先出(last in first off,LIFO)的数据结构,而队列(Queue)则是一种先进先出 (fisrt in first out,...
  • baidu_35561918
  • baidu_35561918
  • 2016年08月07日 16:47
  • 400

Java栈和队列的用例

package com.ipmotor.sm.db; import java.util.LinkedList; import java.util.Queue; import java.uti...
  • u014230945
  • u014230945
  • 2017年01月07日 21:31
  • 80

数据结构实验之栈与队列八:栈的基本操作

Problem Description 堆栈是一种基本的数据结构。堆栈具有两种基本操作方式,push 和 pop。push一个值会将其压入栈顶,而 pop 则会将栈顶的值弹出。现在我们就来验证一...
  • shadowam
  • shadowam
  • 2017年09月27日 14:56
  • 436

栈和队列面试题(一)

1.实现一个栈,要求Push(入栈),Pop(出栈),Min(返回最小值的操作)的时间复杂度为O(1)。 思想:创建两个栈,一个为正常栈S,一个为最小元素栈Minstack,按元素入栈顺序将第一个元素...
  • z_xiao_xue
  • z_xiao_xue
  • 2016年08月20日 10:42
  • 653

23种经典设计模式之策略模式

前言 相信只要是学过java或者其他面向对象编程语言的伙伴们多少都听说过设计模式,比如可以说算是烂大街的mvc、单例模式都是其中之一。当然设计模式的家族很庞大,远远不止这些。那设计模式是用来干什么的呢...
  • ahzpc007
  • ahzpc007
  • 2016年11月03日 16:24
  • 761
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:栈和队列之经典(下)
举报原因:
原因补充:

(最多只允许输入30个字)