数据结构学习 jz09两个栈组成队列

题目:

数据结构学习 jz09两个栈组成队列_第1张图片

思路:

这是一道比较简单的题目,一开始就能想到一个栈专门用来出栈,另一个栈专门用来入栈。但是我实现了之后发现时间特别慢,这让我很纳闷。后来发现有一些细节需要注意。修改了之后速度就上去了。

原本的思路:在出栈和入栈的时候,我都检查了另一个栈有没有数据,如果有数据就switch_stack【注意,这是不对的】

例子:

先给A入栈,相当于往队列存数据。

A:| 1 |  2 | 3 |

B:| |


然后想要出栈,这个时候需要把A的数据腾过来(switch_stack)

A:| |

B:| 3 | 2 | 1 |


出栈吧!

A:| |

B:| 3 | 2 |->1


紧接着,如果现在想要给队列存数据,就得给A入栈。

这个时候我的问题就出现了,我觉得得先把B的数据腾过来再做入栈,我觉得两个栈必须有一个是空的才对!

所以我先检查B是否为空,把B的数据推回给A,再让A入栈。

A: |  2 | 3 |<-4

B:| |

但其实不用这么麻烦的,这样会消耗很多内存和时间。

更新后的思路:在出栈的时候,只在B(负责出栈的栈)为空的时候才把A的数据腾过来就好了,这样顺序既不会乱,也大幅度减少了来回倒腾的次数。

例子:

先给A入栈,相当于往队列存数据。

A:| 1 |  2 | 3 |

B:| |


然后想要出栈,这个时候需要把A的数据腾过来(switch_stack)

A:| |

B:| 3 | 2 | 1 |


出栈吧!

A:| |

B:| 3 | 2 |->1


这里就是和原来的差别:

紧接着,如果现在想要给队列存数据,就得给A入栈。

直接给A入栈就好了,不需要检查什么的。我当初以为这样会打乱顺序,但其实不会啦~

A:| |<-4 <-5

B:| 3 | 2 |


如果这个时候需要弹出B两次,弹出完之后B就是空着的:

A:| 4 | 5 |

B:| |


噢!这个时候如果想再弹出,才会因为B是空着的,触发switch_stack,把A的数据拎过来。

A:| |

B:| 5 | 4 |

不会打乱顺序的关键:在B为空的时候才把A的数据拿过来。

更新后的代码:

更新之前是出入都有switch_stack的。

#include 
//时间复杂度O(N):appendTail()函数为 O(1);deleteHead() 函数在 N次队首元素删除操作中总共需完成 N个元素的倒序。
//空间复杂度O(N):最差情况下,栈 A 和 B 共保存 N 个元素。

class CQueue {
public:
    CQueue() {}
    void appendTail(int value) {
        A.push(value);
    }
    int deleteHead() {
        if (B.empty() && A.empty())
            return -1;
        if (B.empty() && !A.empty())//在B为空的时候需要检查A
            switch_stack(A, B);
        int v = B.top();
        B.pop();
        return v;
    }
private:
    std::stack A;//入
    std::stack B;//出
    void switch_stack (std::stack& l, std::stack& r)//l->r
    {
        while (!l.empty())
        {
            r.push(l.top());
            l.pop();
        }
    }
};


void Test_solution()
{
    CQueue* obj = new CQueue();
    //obj->appendTail(1);
    int param_2 = obj->deleteHead();
}

复杂度计算:

时间复杂度O(N):appendTail()函数为 O(1);deleteHead() 函数在 N次队首元素删除操作中总共需完成 N个元素的倒序。
空间复杂度O(N):最差情况下,栈 A 和 B 共保存 N 个元素。

你可能感兴趣的:(数据结构学习,数据结构,学习,算法)