定义栈的数据结构____<2>
定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。 要求函数min、push以及pop的时间复杂度都是O(1)。
无论使用链表还是数组实现的栈,push和pop操作的时间复杂度都是O(1)。所以,难点在于实现min使其时间复杂度也是O(1)。该堆栈需要新增一个元素minPoint指针。假设目前minPoint指针指向最小元素,push(data),若data比minPoint指向的元素还小,那么minPoint指向data。再pop(),此时minPoint指向的最小元素不再存在于堆栈中,需要修改minPoint指针。因此,仅仅依靠一个minPoint指针无法顺利实现功能。
考虑用另外一个堆栈minStack来存储minPoint指针依次指向的元素,其中minStack的首元素指向当前的最小元素。当push(data),且data比最小元素还小时,把新节点也Push入minStack;否则,直接把data入栈。当pop()时,如果当前要弹出的元素是栈的最小元素,则在minStack中同时出栈,以更改最小元素;否则只弹出当前栈定元素。
思路:Push第一个元素进入A,同时也Push进辅助栈B,当向A中Push的元素比B中的元素小,也将此元素Push进B(即更新B),否则B栈保持不动(即Push指针minPoint指向的值)。
向栈 A push 元素时,顺序由下至上。
辅助栈 B 中,始终保存着最小的元素。
1 #include<iostream>
2 #include<stack>
3
4 using namespace std;
5
6 //自己定义的栈
7 template<class T>
8 class Stack{
9 private:
10 stack<T> s; //主栈
11 stack<T> minS; //辅助栈
12 public:
13 bool empty(void);
14 T pop(void);
15 void push(T elem);
16 T min(void);
17 };
18
19 template<class T>
20 T Stack<T>::pop(void){
21 T elem=s.top();
22 s.pop();
23 minS.pop();
24 return elem;
25 }
26
27 template<class T>
28 T Stack<T>::min(void){
29 return minS.top();
30 }
31
32 template<class T>
33 void Stack<T>::push(T elem){ //关键
34 s.push(elem);
35 if(minS.empty())
36 {minS.push(elem);} //若是首元素则进辅助栈
37 else{ //若不是则与辅助栈顶元素比较
38 T temp=minS.top();
39 if(temp<elem) minS.push(temp);
40 else minS.push(elem);
41 }
42 }
43
44
45 template<class T>
46 bool Stack<T>::empty(void){
47 return s.empty();
48 }
49
50
51 int main(void)
52 {
53 Stack<int> my;
54 my.push(4);
55 cout<<my.min()<<endl;
56 my.push(8);
57 cout<<my.min()<<endl;
58 my.push(0);
59 cout<<my.min()<<endl;
60 my.pop();
61 cout<<my.min()<<endl;
62
63 return 0;
64 }
声明和使用类模板:
(1) 先写出一个实际的类。由于其语义明确,含义清楚,一般不会出错。
(2) 将此类中准备改变的类型名(如int要改变为float或char)改用一个自己指定的虚拟类型名(如numtype)。
(3) 在类声明前面加入一行,格式为:
template<class 虚拟类型参数>,
如
template<class numtype> //注意本行末尾无分号
class Compare
{…}; //类体
(4) 用类模板定义对象时用以下形式:
类模板名<实际类型名> 对象名;
类模板名<实际类型名> 对象名(实参表列);
如
Compare<int> cmp;
Compare<int> cmp(3,7);
(5) 如果在类模板外定义成员函数,应写成类模板形式:
template<class 虚拟类型参数>
函数类型 类模板名<虚拟类型参数>∷成员函数名(函数形参表列) {…}
说明:
(1)类模板的类型参数可以有一个或多个,每个类型前面都必须加class,
如 template<class T1,class T2>
class someclass
{…};
在定义对象时分别代入实际的类型名,如
someclass<int,double> obj;
(2) 和使用类一样,使用类模板时要注意其作用域,只能在其有效作用域内用它定义对象。
(3) 模板可以有层次,一个类模板可以作为基类,派生出派生模板类。
本文来自:http://www.cnblogs.com/aLittleBitCool/archive/2011/01/15/1936466.html ,感谢moonApple 的分享。