您的位置:首页 > 职场人生

队列和栈相关面试题总结

2017-05-23 23:49 369 查看
1、实现一个栈,要求实现Push(出栈)、Pop(入栈)、Min(返回最小值的操作)的时间复杂度为O(1)??
分析:
     出栈和入栈根据栈自身提供的接口不难实现,而返回最小值,我们知道遍历一次栈即可找到最小值,但是对栈的操作只能在栈顶,因此,要遍历势必要改变栈的状态,而且还要求时间复杂度为O(1),即更不能遍历栈。我们可以利用两个栈同时进行操作,一个是我们放数据的栈,而另一个栈顶专门放数据中的最小值,最后需要当前最小值,直接取第二个栈顶元素即可。



2、源代码如下:
//push出栈   ------     pop入栈           min返回最小值 ------   时间复杂度为O(1)

//不能遍历

#include <iostream>
using namespace std;
#include <stack>

template <class T>
class StackMinValue
{
public:
StackMinValue()
{}
void Pop(const T& x)
{
s.push(x);
if(min.empty())
{
min.push(x);
}
else if(min.top()>=x)
{
min.push(x);
}
}
void Push()   //出栈
{
if(min.top() == s.top() && s.size() != 1)
{
min.pop();
}
s.pop();
}
T& Min()
{
return min.top();
}
~StackMinValue()
{}
private:
stack<T> s,min;
};

int main()
{
StackMinValue<int> a;
a.Pop(3);
a.Pop(2);
cout<<a.Min();
a.Pop(5);
a.Pop(8);
a.Pop(1);
cout<<a.Min();
a.Push();
a.Push();
cout<<a.Min();
a.Push();
a.Push();
cout<<a.Min();

return 0;
}
2、使用两个栈实现一个队列
分析:栈--->先进后出                        队列--->先进先出
在进行操作时,我们可利用栈的特性,在进行push操作时,使用栈操作,而进行pop操作时将栈中元素逐一放入另一栈
源代码:
#include <iostream>
using namespace std;
#include <stack>
#include <assert.h>
template<class T>
class Queue
{
public:
Queue()
{}
void Push(const T& x)  //尾插
{
a.push(x);
}
void Pop()            //头删
{
assert(!a.empty());
while(!a.empty())
{
b.push(a.top());
a.pop();
}
b.pop();
while(!b.empty())
{
a.push(b.top());
b.pop();
}
}
size_t Size()
{
return a.size();
}
bool Empty()
{
return a.empty();
}
T& front()     //返回队头元素 -------找到再恢复
{
assert(a.empty() != true);
while (!a.empty())
{
b.push(a.top());
a.pop();
}
T tmp = b.top();
while (!b.empty())
{
a.push(b.top());
b.pop();
}
return tmp;
}
T& back()     //返回队尾元素
{
return a.top();
}
~Queue()
{}
private:
stack<T> a,b;
};
int main()
{
Queue<int> a;
a.Push(1);
a.Push(2);
a.Push(3);
cout<<a.front()<<endl;
cout<<a.Size()<<endl;
a.Push(4);
a.Pop();
cout<<a.front()<<endl;
return 0;
}


3、两个队列实现栈
思路:栈---先进后出    队列---先进先出
创建两个队列,一个队列放数据,另一个当作辅助队列,当进行push(尾插)操作时直接用队列的push进行操作,而进行pop操作时,由于队列的pop是进行头删,不符合栈pop的条件,这时可将队列1中数据从第一个开始另一辅助队列2中,但是,第一个队列中最后一个元素不放入,然后,将第一个队列清空,再将辅助队列中元素按顺序放入第一个队列中即可。
源代码:
#include <iostream>
using namespace std;
#include <queue>
#include <assert.h>
// 两个队列实现一个栈
template <class T>
class TStack
{
public:
TStack()
{}
void Push(const T& x) //进栈---尾插
{
s1.push(x);
}
void Pop()   //出栈---
{
assert(!s1.empty());
while (!s1.empty() && (s1.size()!=1))    //最后一个元素不进队列
{
s2.push(s1.front());
s1.pop();
}
s1.pop();
while (!s2.empty())
{
s1.push(s2.front());
s2.pop();
}
}
bool Empty()
{
if (s1.empty())
{
return true;
}
return false;
}
T& Top()
{
return s1.back();
}
size_t Size()
{
return s1.size();
}

private:
queue<T> s1,s2;
};

int main()
{
TStack<int> a;
a.Push(1);
a.Push(7);
a.Push(5);
a.Push(6);
cout<<a.Top()<<endl;
cout<<a.Size()<<endl;
a.Pop();
cout<<a.Size()<<endl;
cout<<a.Top()<<endl;
return 0;
}


4、一个数组实现两个栈
分析:
方案一:将数组的下标为0的位置当做第一个栈的栈底,下标为1的位置当做第二个栈的栈底,将数组的偶数位置看做第一个栈的存储空间,奇数位置看做第二个栈的存储空间。

方案二:从中间分别向两边压栈
将数组的中间位置看做两个栈的栈底,压栈时栈顶指针分别向两边移动,当任何一边到达数组的起始位置或是数组尾部,则开始扩容。

方案三:从两边向中间压栈
将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。

比较:方案二和方案一当两栈中元素不同时,比较浪费空间,方案三节省空间
方案3代码:
#include <iostream>
using namespace std;
#include <assert.h>
//一个数组实现两个栈
//从两边开始存
template<class T>
class Stack
{
public:
Stack()
:_arr(NULL)
,_size1(0)
,_size2(0)
,_capacity(0) //初始化容量为2
{}
void Push1(const T& x)
{
_checkcapacity();
_arr[_size1] = x;
_size1++;
}
void Pop1()
{
assert(Size1() != 0);
_size1--;
}
size_t Size1()
{
return _size1;
}
T& Top1()
{
return _arr[_size1-1];
}
void Push2(const T& x)
{
_checkcapacity();
size_t botton = _capacity-_size2-1;
_arr[botton] = x;
botton--;
_size2++;
}

void Pop2()
{
assert(Size2() != 0);
_size2--;
}
size_t Size2()
{
return _size2;
}
T& Top2()
{
assert(_size2 != 0);
return _arr[_capacity-1];
}
private:
void _checkcapacity()
{
if ((_size1+_size2)==_capacity || (_capacity==0)) //容量满 或 空
{
size_t _newcapacity = _capacity*2+2;
T* tmp = new T[_newcapacity];
for (size_t i=0; i<_size1; i++) //第一个栈放数组左边
{
tmp[i] = _arr[i];
}
size_t t = _capacity-1;
for(size_t j=_newcapacity-1; (j>(_newcapacity-_size1)) && (t>_size1-1); --t,j--)
{
tmp[j] = _arr[t];
}
_capacity = _newcapacity;
swap(_arr,tmp);
}
}
private:
T* _arr;
size_t _size1;
size_t _size2;
size_t _capacity;
};

int main()
{
Stack<int> a;
a.Push1(1);
cout<<a.Size1()<<endl;
a.Push1(8);
a.Pop1();
a.Push1(5);
a.Push1(3);
cout<<a.Size1()<<endl;
cout<<a.Top1()<<endl;
a.Push1(2);
a.Push2(1);
a.Push2(0);
a.Push2(4);
cout<<a.Size2()<<endl;
cout<<a.Top2()<<endl;
a.Push2(1);
a.Push2(1);
a.Push2(4);
a.Push2(10);
a.Pop1();
cout<<a.Size2()<<endl;
a.Pop1();
a.Pop2();
a.Pop2();
cout<<a.Size2()<<endl;
cout<<a.Top2()<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息