面试题——栈与队列的应用(下)
2016-04-18 20:10
393 查看
栈与队列的应用 在“栈与队列的应用(上)”中,通过讨论两个队列实现一个栈和两个栈实现一个队列这两个问题,我们对栈和队列也有了更深的了解,下面我们主要来讨论以下两个面试中常常会遇到的问题:
1)一个数组实现两个栈
2)实现一个栈,能够push、pop、min(求栈中最小的数据)
问题一:
对于一个数组,我们如何能够使其成为两个栈?根据数组和栈的特点,我们不难发现可以将数组的两端作为栈的栈底,使用两个指针分别指向数组的开始位置和末尾位置,假设将数组的左边作为栈s1,数组的右边作为栈s2,若s1中的栈顶指针向后在偏移一个位置与另一个指针同时指向一块空间,此时就称为“栈满”,不能进行插入操作。如果想要对栈进行操作,就必须要指定对哪个栈操作。这里使用了两个整形变量用来记录栈s1和栈s2的栈顶的位置下标,对其进行操作。
下面为简单的图示:
下面是具体的程序代码:
问题二:
这个问题主要是要实现求栈中最小数据,完成这个功能,就需要借助另一个栈对最小数据进行保存,假设现有栈s1和栈s2,当向s1中插入第一个数据时,同时也向s2中插入相同的数据,下来在向s1中插入第二个数据,此时若第二个数据小于s2的栈顶数据,此时也将与之相同的数据插入s2中,若第二个数据小于s2的栈顶数据,则不用向s2中插入数据,按照这样的方式插入数据。现在就能够显而易见的知道s2中的栈顶数据就是栈s1中的最小数据。
如果需要对s1中数据进行删除,如若s1中要删除的数据与s2中要删除的数据相同,则栈s2中同样删除栈顶元素,若不等,则将s1中栈顶元素删除就行,不需要删除s2中的数据。这样就能够始终保持s2中栈顶数据为栈s1中的最小数据。
下面是简单的图示:
下面为具体的程序代码:
1)一个数组实现两个栈
2)实现一个栈,能够push、pop、min(求栈中最小的数据)
问题一:
对于一个数组,我们如何能够使其成为两个栈?根据数组和栈的特点,我们不难发现可以将数组的两端作为栈的栈底,使用两个指针分别指向数组的开始位置和末尾位置,假设将数组的左边作为栈s1,数组的右边作为栈s2,若s1中的栈顶指针向后在偏移一个位置与另一个指针同时指向一块空间,此时就称为“栈满”,不能进行插入操作。如果想要对栈进行操作,就必须要指定对哪个栈操作。这里使用了两个整形变量用来记录栈s1和栈s2的栈顶的位置下标,对其进行操作。
下面为简单的图示:
下面是具体的程序代码:
//一个数组实现两个栈 //方法一:(静态数组) #include <iostream> using namespace std; #include <stdlib.h> #define MAX 100 template <class T> class TwoStack { public: TwoStack() //构造函数 :_array(new T[MAX]) , lefttop0(-1) , righttop1(MAX) { } public: void Push(T x, int i) //压栈,将数据压入i号栈中 { if (lefttop0 + 1 == righttop1) { cout << "栈已满,不能压栈!"; return; } else { switch (i) { case 0: //压入0号栈中 lefttop0++; _array[lefttop0] = x; break; case 1: //压入1号栈中 righttop1--; _array[righttop1] = x; break; default: break; } } } void Pop(int i) //i号栈、元素出栈 { switch (i) { case 0: if (lefttop0 == -1) { cout << "The Stack is Empty!" << endl; } lefttop0--; break; case 1: if (righttop1 == MAX) { cout << "The Stack is Empty!" << endl; } righttop1++; break; default: break; } } T& top(int i) //读取i号栈中元素 { if (i == 0) { return _array[lefttop0]; } else { return _array[righttop1]; } } void Display(int i) //打印i号栈的元素 { if (i == 0) { cout << "打印0号栈中的元素:" << endl; while (lefttop0 != -1) { cout << _array[lefttop0] << " "; lefttop0--; } cout << endl; } else if (i == 1) { cout << "打印1号栈中的元素:" << endl; while (righttop1 != MAX) { cout << _array[righttop1] << " "; righttop1++; } cout << endl; } } private: T* _array; int lefttop0; int righttop1; };
问题二:
这个问题主要是要实现求栈中最小数据,完成这个功能,就需要借助另一个栈对最小数据进行保存,假设现有栈s1和栈s2,当向s1中插入第一个数据时,同时也向s2中插入相同的数据,下来在向s1中插入第二个数据,此时若第二个数据小于s2的栈顶数据,此时也将与之相同的数据插入s2中,若第二个数据小于s2的栈顶数据,则不用向s2中插入数据,按照这样的方式插入数据。现在就能够显而易见的知道s2中的栈顶数据就是栈s1中的最小数据。
如果需要对s1中数据进行删除,如若s1中要删除的数据与s2中要删除的数据相同,则栈s2中同样删除栈顶元素,若不等,则将s1中栈顶元素删除就行,不需要删除s2中的数据。这样就能够始终保持s2中栈顶数据为栈s1中的最小数据。
下面是简单的图示:
下面为具体的程序代码:
//判断出对序列中的最小数据 //实现一个栈,要求实现Push、pop、min(返回栈中最小值)的时间复杂度为o(1)。 #include <iostream> using namespace std; #include <stdlib.h> #include <stack> template <class T> class Stack { public: void Push(const T& x) { if (s1.empty() && s2.empty()) { s1.push(x); s2.push(x); } else if (!s1.empty()) { if (x < s2.top()) { s1.push(x); s2.push(x); } else { s1.push(x); } } } void Pop() { if (!s1.empty() && !s2.empty()) { if (s1.top() == s2.top()) { s1.pop(); s2.pop(); } else { s1.pop(); } } } T minNumber() { return s2.top(); } private: stack<T> s1; stack<T> s2; };
相关文章推荐
- 一个关于if else容易迷惑的问题
- 一道sql面试题附答案
- C# 超高面试题收集整理
- C#线程队列用法实例分析
- 算法系列15天速成 第九天 队列
- C++基于栈实现铁轨问题
- C语言单链队列的表示与实现实例详解
- C语言栈的表示与实现实例详解
- C语言实现颠倒栈的方法
- 算法系列15天速成 第十天 栈
- mysql 队列 实现并发读
- C#队列Queue用法实例分析
- C#多线程处理多个队列数据的方法
- 人人网javascript面试题 可以提前实现下
- C语言循环队列的表示与实现实例详解
- C++循环队列实现模型
- C#内置队列类Queue用法实例
- 一看就懂:图解C#中的值类型、引用类型、栈、堆、ref、out
- Array栈方法和队列方法的特点说明
- Linux运维工程师笔试题第十三套