栈和队列的相关面试题
2017-07-20 18:08
429 查看
栈和队列相关面试题
栈的特性是先入后出,而队列的特性则是先入先出
1.使用数组建立一个动态栈
这个题目其实就是最基础的实现方法,所以就不多介绍,直接贴代码了。
2.包含min函数的栈
题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调用min、push、pop的时间复杂度都是O(1)
这个题目相对简单的做法就是借助辅助栈,每次都把最小的元素(之前最小的元素和新插入的元素间的较小者)存放进另一个辅助栈。每次都将当前的最小值元素存放进辅助栈,不会影响数据栈中的压入、弹出顺序,也能保证辅助栈的栈顶元素始终是当前插入的所有元素中的最小值。
在这里我借助图来讲解这个过程
由这个图就可以很清晰的看出来这种方法是可行的。实现方法也比较简单,借助STL里的栈可以很容易的实现这个功能。
3.栈的压入、弹出序列
题目:输入两个整数序列,第一个序列表示栈的压入序列,请判断第二个序列是否为该栈的弹出序列。假设压入栈的所有数字均不相等。
例如序列1、2、3、4、5是某栈的压栈序列,序列4、5、3、2、1是该压栈序列对应的一个弹出序列。但4、3、5、1、2就不可能是该压栈序列的弹出序列
借助图应该会更容易理解这个过程
4.用两个栈实现队列
题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入节点和在队列头部删除节点的功能
template<typename T>
class CQueue
{
public:
CQueue(void);
~Queue(void);
void appendTail(const T& node);
T deleteHead();
private:
stack<T> stack1;
stack<T> stack2;
}
根据栈和队列的特性来实现,一个栈负责删除,一个栈负责插入
5.用两个队列实现栈
题目:用两个队列实现一个栈,能够完成在栈顶插入节点,在栈顶删除节点的功能
将一个队列作为辅助中转站,队列的插入、删除都在另一个栈中实现
6.使用数组实现队列
实现尾插和头删功能即可
7.一个数组实现两个栈
把握栈的特性,即对于数组来说就是尾插功能和尾删功能,满足这两个功能主要即可
对于这个题有三种组织形式,主要在扩容时有差别
(1)第一种:从中间向两边压栈
采用两个栈底分别放在数组中间,栈顶向两边移动,当两个栈顶任意一个到达数组的两边时,数组进行扩容
(2)第二种:两边向中间压栈
两个栈的栈底分别在数组的两边,压栈时栈顶向中间靠拢,当两个栈顶相遇时扩容
(3)第三种:分奇偶方式压栈
采用交叉索引的方式,两个栈分别拥有下标奇偶的空间,假设数组原本容量是偶数,当偶数栈的栈顶达到容量-1时或奇数栈的栈顶达到容量-2时扩容
第一种和第三种在扩容时考虑的情况比较复杂,并且在一个栈数据多,一个栈数据少时,空间浪费比较大,我在这里只实现第二种方法
所以代码的地址:
https://github.com/zknn/VS2013Copy/blob/%E6%A0%88%E5%92%8C%E9%98%9F%E5%88%97%E7%9A%84%E9%9D%A2%E8%AF%95%E9%A2%98/StackQueue/%E6%BA%90.cpp
栈的特性是先入后出,而队列的特性则是先入先出
1.使用数组建立一个动态栈
这个题目其实就是最基础的实现方法,所以就不多介绍,直接贴代码了。
//1.借助数组实现栈 template class StackArr { public: StackArr() :_a(NULL) , _size(0) , _capacity(0) {} void Push(T data) { checkcapacity(); _a[_size] = data; _size++; } void Pop() { if (_size) { _size--; return; } cout << "栈为空" << endl; } void checkcapacity() { _capacity = _capacity * 2 + 3; T* tmp = new T[_capacity]; if (_a) { for (int i = 0; i < _size; i++) { tmp[i] = _a[i]; } delete[] _a; } _a = tmp; } int Size() { return _size ; } bool Empty() { return _size > 0 ? true : false; } T Top() { return _a[--_size]; } protected: T* _a; int _size; int _capacity; }; void testStackArr() { StackArr s; s.Push(1); s.Push(2); s.Push(3); s.Push(4); cout << s.Size() << endl; cout << s.Empty() << endl; cout << s.Top() << endl; s.Pop(); s.Pop(); s.Pop(); s.Pop(); s.Pop(); s.Pop(); s.Pop(); cout << s.Empty() << endl; }
2.包含min函数的栈
题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调用min、push、pop的时间复杂度都是O(1)
这个题目相对简单的做法就是借助辅助栈,每次都把最小的元素(之前最小的元素和新插入的元素间的较小者)存放进另一个辅助栈。每次都将当前的最小值元素存放进辅助栈,不会影响数据栈中的压入、弹出顺序,也能保证辅助栈的栈顶元素始终是当前插入的所有元素中的最小值。
在这里我借助图来讲解这个过程
由这个图就可以很清晰的看出来这种方法是可行的。实现方法也比较简单,借助STL里的栈可以很容易的实现这个功能。
//2.包含min函数的栈 class StackMin { public: void Push(int data) { data_stack.push(data); if (min_stack.empty() == true) { min_stack.push(data); } else if (min_stack.empty() == false && min_stack.top()>=data) { min_stack.push(data); } } void Pop() { if (data_stack.empty() == true) { cout << "栈为空" << endl; return; } if (min_stack.empty() == false && min_stack.top() == data_stack.top()) { data_stack.pop(); min_stack.pop(); } else { data_stack.pop(); } } int Min() { return min_stack.top(); } protected: stack data_stack; stack min_stack; };
3.栈的压入、弹出序列
题目:输入两个整数序列,第一个序列表示栈的压入序列,请判断第二个序列是否为该栈的弹出序列。假设压入栈的所有数字均不相等。
例如序列1、2、3、4、5是某栈的压栈序列,序列4、5、3、2、1是该压栈序列对应的一个弹出序列。但4、3、5、1、2就不可能是该压栈序列的弹出序列
借助图应该会更容易理解这个过程
//3.栈的压入和弹出序列 bool IsPoporder(const int* pushorder, const int* poporder, int length) { bool possible = false; if (pushorder != NULL&&poporder != NULL&&length > 0) { c47f const int* pushnext = pushorder; const int* popnext = poporder; stack data_stack; while (popnext - poporder < length) { while (data_stack.empty() || data_stack.top() != *popnext) { if (pushnext - pushorder == length) break; data_stack.push(*pushnext); pushnext++; } if (data_stack.top() != *popnext) break; data_stack.pop(); popnext++; } if (data_stack.empty() && popnext - poporder == length) { possible = true; } } return possible; }
4.用两个栈实现队列
题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入节点和在队列头部删除节点的功能
template<typename T>
class CQueue
{
public:
CQueue(void);
~Queue(void);
void appendTail(const T& node);
T deleteHead();
private:
stack<T> stack1;
stack<T> stack2;
}
根据栈和队列的特性来实现,一个栈负责删除,一个栈负责插入
/4.用两个栈模拟实现一个队列 class SQueue { public: void Push(int data) { pushstack.push(data); } void Pop() //为检测删除是否正确 { if (pushstack.empty() == true && popstack.empty() == true) { cout << "当前队列为空" << " "; return ; } if (popstack.empty() == true) { while (pushstack.empty() == false) { popstack.push(pushstack.top()); pushstack.pop(); } } cout << "删除" << popstack.top() << endl; popstack.pop(); } private: stack pushstack; stack popstack; };
5.用两个队列实现栈
题目:用两个队列实现一个栈,能够完成在栈顶插入节点,在栈顶删除节点的功能
将一个队列作为辅助中转站,队列的插入、删除都在另一个栈中实现
#include //5.两个队列实现一个栈 class QStack { public: void Push(int data) { q1.push(data); } void Pop() { if (q1.empty() == true && q2.empty() == true) { cout << "当前栈为空" << endl; return; } if (!q1.empty()) { while (q1.size() > 1) { q2.push(q1.front()); q1.pop(); } cout << "删除" << q1.front() << endl; q1.pop(); while (q2.empty() == false) { q1.push(q2.front()); q2.pop(); } } } private : queue q1; queue q2; };
6.使用数组实现队列
实现尾插和头删功能即可
/6.用数组实现队列(实现尾插头删) template class QueueArr { public: QueueArr() :_a(NULL) , _size(0) , _capacity(0) {} void Push(T data) { checkcapacity(); _a[_size] = data; ++_size; } void Pop() { if (_size==0) { cout << "当前队列为空" << endl; return; } if (_size>0) { int i = 0; for (int i = 0; i < _size; ++i) { _a[i] = _a[i - 1]; } --_size; } } void checkcapacity() { _capacity = _capacity * 2 + 3; T* tmp = new T[_capacity]; if (_size>0) { for (int i = 0; i < _size; i++) { tmp[i] = _a[i]; } delete[] _a; } _a = tmp; } private: T* _a; int _size; int _capacity; };
7.一个数组实现两个栈
把握栈的特性,即对于数组来说就是尾插功能和尾删功能,满足这两个功能主要即可
对于这个题有三种组织形式,主要在扩容时有差别
(1)第一种:从中间向两边压栈
采用两个栈底分别放在数组中间,栈顶向两边移动,当两个栈顶任意一个到达数组的两边时,数组进行扩容
(2)第二种:两边向中间压栈
两个栈的栈底分别在数组的两边,压栈时栈顶向中间靠拢,当两个栈顶相遇时扩容
(3)第三种:分奇偶方式压栈
采用交叉索引的方式,两个栈分别拥有下标奇偶的空间,假设数组原本容量是偶数,当偶数栈的栈顶达到容量-1时或奇数栈的栈顶达到容量-2时扩容
第一种和第三种在扩容时考虑的情况比较复杂,并且在一个栈数据多,一个栈数据少时,空间浪费比较大,我在这里只实现第二种方法
//7.一个数组实现两个栈 template class ArrayStack { public: ArrayStack() :_arr1(new T[1]) , _size1(0) , _size2(0) , _capacity(1) , _sz(_capacity-1) { assert(_arr1); _arr2 = &_arr1[_capacity - 1]; } ~ArrayStack() { if (!_arr1) { delete[] _arr1; _size1 = 0; _capacity = 0; _size2 = 0; _sz = 0; } } void arr1_Push(T data) { checkcapacity(); _arr1[_size1] = data; _size1++; } void arr2_Push(T data) { checkcapacity(); _arr1[_capacity-_size2-1] = data; _size2++; } void arr1_Pop() { if (_size1 > 0) { _size1--; } else { cout << "栈1为空" << endl; } } void arr2_Pop() { if (_size2) { _size2--; } else { cout << "栈2为空" << endl; } } void arr1_Display() { for (int i = 0; i < _size1; i++) { cout << _arr1[i] << " "; } cout << "NULL"<_capacity-_size2-1; i--) { cout << _arr1[i] << " "; } cout <<"NULL"<< endl; } void Display() { for (int i = 0; i < _capacity; i++) { cout << _arr1[i] << " "; } cout << "NULL" << endl; } void checkcapacity() { if (&_arr1[_size1]==&_arr1[_capacity-_size2-1]) { int s = _size2; int t_capacity = _capacity * 2 + 3; int t =t_capacity; T* tmp = new T[t_capacity]; for (int i = 0; i < _size1; i++) { tmp[i] = _arr1[i]; } while (s--) { tmp[t - 1] = _arr1[_capacity - 1]; t--; _capacity--; } delete[] _arr1; _arr1 = tmp; _capacity = t_capacity; _arr2 = &_arr1[_capacity - 1]; _sz = _capacity - 1; } } private: T* _arr1; T* _arr2; int _size1; int _size2; int _capacity; //两个栈共用的容量 int _sz; };
所以代码的地址:
https://github.com/zknn/VS2013Copy/blob/%E6%A0%88%E5%92%8C%E9%98%9F%E5%88%97%E7%9A%84%E9%9D%A2%E8%AF%95%E9%A2%98/StackQueue/%E6%BA%90.cpp
相关文章推荐
- 栈和队列的相关面试题
- 【程序员面试宝典】栈和队列相关面试题
- 栈和队列相关面试题2
- 栈和队列 相关 面试题
- 栈和队列相关面试题
- 栈和队列相关面试题(2)
- 面试题7—相关题目(两个队列实现栈)
- 栈和队列相关面试题(3)
- 栈和队列 相关 面试题
- 栈和队列相关面试题(1)
- 栈和队列相关面试题(1)
- 剑指offer编程题Java实现——面试题7相关题用两个队列实现一个栈
- 队列和栈相关面试题总结
- 栈与队列相关面试题
- java——栈和队列 面试题
- 面试题:堆和队列
- Python工程师面试题 与Python基础语法相关
- 面试题7(1):用2个栈实现队列
- c语言指针相关面试题
- 《算法导论》第六章之堆和优先级队列相关算法C语言实现