自定义栈-pop-push-min-时间复杂度都为O(1)
1. 简述
首先要决定使用链表结构实现还是顺序结构实现,对于顺序结构实现,当数据满的情况下进行Push时,需要开辟新的数组,进行复制,因此不能保证Push的时间复杂度为O(1);链表结构能够保证Push和Pop的时间复杂度为O(1)。Min的时间复杂度也要求O(1),通过空间换时间,分别记录链表,当包含一个节点时,最小值所在的节点,当包含两个节点时,最小值所在的节点,等等,直到所有节点时,最小值所在的节点。这样相当于两个链表,一个链表保存数值,另一个链表保存第一个链表中,对应节点范围内的最小值所在节点。
2. 实现
#include <iostream>
using namespace std;
// 友元,链接结构
template<class T>
class Stack;
template<class T>
class Node {
friend class Stack<T>;
private:
T data;
Node<T>* link;
};
template<class T>
class MinNode {
friend class Stack<T>;
private:
Node<T>* min_node;
MinNode<T>* link;
};
template<class T>
class Stack {
private:
Node<T>* head;
MinNode<T>* min_head;
public:
Stack(): head(0),min_head(0) { }
~Stack() {
Node<T>* tmp;
while(head) {
tmp = head->link;
delete head;
head = tmp;
}
tmp = 0;
MinNode<T>* min_tmp;
while(min_head) {
min_tmp = min_head->link;
delete min_head;
min_head = min_tmp;
}
min_tmp = 0;
}
Stack<T>& Push(const T& data) {
Node<T>* tmp = new Node<T>;
tmp->data = data;
tmp->link = head;
head = tmp;
MinNode<T>* min_tmp = new MinNode<T>;
if(min_head > 0 && min_head->min_node->data < head->data)
min_tmp->min_node = min_head->min_node;
else
min_tmp->min_node = head;
min_tmp->link = min_head;
min_head = min_tmp;
return *this;
}
Stack<T>& Pop() {
assert(head > 0);
Node<T> *tmp = head->link;
using namespace std;
// 友元,链接结构
template<class T>
class Stack;
template<class T>
class Node {
friend class Stack<T>;
private:
T data;
Node<T>* link;
};
template<class T>
class MinNode {
friend class Stack<T>;
private:
Node<T>* min_node;
MinNode<T>* link;
};
template<class T>
class Stack {
private:
Node<T>* head;
MinNode<T>* min_head;
public:
Stack(): head(0),min_head(0) { }
~Stack() {
Node<T>* tmp;
while(head) {
tmp = head->link;
delete head;
head = tmp;
}
tmp = 0;
MinNode<T>* min_tmp;
while(min_head) {
min_tmp = min_head->link;
delete min_head;
min_head = min_tmp;
}
min_tmp = 0;
}
Stack<T>& Push(const T& data) {
Node<T>* tmp = new Node<T>;
tmp->data = data;
tmp->link = head;
head = tmp;
MinNode<T>* min_tmp = new MinNode<T>;
if(min_head > 0 && min_head->min_node->data < head->data)
min_tmp->min_node = min_head->min_node;
else
min_tmp->min_node = head;
min_tmp->link = min_head;
min_head = min_tmp;
return *this;
}
Stack<T>& Pop() {
assert(head > 0);
Node<T> *tmp = head->link;
delete head;
head = tmp;
tmp = 0;
MinNode<T> *min_tmp = min_head->link;
MinNode<T> *min_tmp = min_head->link;
delete min_head;
min_head = min_tmp;
min_tmp = 0;
return *this;
}
void Min(T& data) {
assert(head > 0);
data = min_head->min_node->data;
}
};
int main() {
Stack<int> stack;
int min;
int array[10] = {3,4,5,6,7,2,1,0,9,8};
for(int i=0; i<10; i++) {
stack.Push(array[i]);
stack.Min(min);
cout << min << endl;
}
system("PAUSE");
return 0;
}return *this;
}
void Min(T& data) {
assert(head > 0);
data = min_head->min_node->data;
}
};
int main() {
Stack<int> stack;
int min;
int array[10] = {3,4,5,6,7,2,1,0,9,8};
for(int i=0; i<10; i++) {
stack.Push(array[i]);
stack.Min(min);
cout << min << endl;
}
system("PAUSE");
return 0;
3. 说明
· 对于Node, MinNode这样的节点类,把Stack声明为其友元,方便直接使用节点类的私有成员。
· Push和Pop返回值类型为Stack<int>&,这样做是为了实现stack.push(1).push(2).push(3);这样调用方式。
· 在参考资料中,有一份使用deque来实现内部结构的实现方式。
4. 参考
程序员面试题精选100题(02)-设计包含min函数的栈
http://zhedahht.blog.163.com/blog/static/25411174200712895228171/