- 重点理解swap, reverse两个函数的实现, 另外任何一个类中涉及到深赋值重点关注拷贝构造函数和clear函数,这两个函数是最容易出内存问题的,new和delete必须成对使用
下面是代码的实现
#ifndef STACK_H__
#define STACK_H__
#include<iostream>
template<typename T>
class Stack {
private:
struct Node {
T element;
Node* next;
Node(T ele, Node* n = NULL):element(ele), next(n) {}
// 此处特别注意初始化列表与赋值符的不同
};
Node* top_node;
size_t node_num;
public:
Stack() {
top_node = NULL;
node_num = 0;
}
Stack(const Stack<T> & stack) {
if (this == &stack) return;
if (stack.top_node != NULL) {
top_node = new Node(stack.top_node->element);
Node* temp = stack.top_node->next;
Node* p = top_node;
while (temp) {
p->next = new Node(temp->element);
temp = temp->next;
p = p->next;
}
node_num = stack.node_num;
} else {
top_node = NULL;
node_num = 0;
}
}
~Stack() {
this->clear();
}
bool empty() {
return node_num == 0;
}
size_t size() const {
return node_num;
}
T top() const {
return top_node->element;
}
void push(T element) {
Node* temp = new Node(element, top_node);
top_node = temp;
++node_num;
}
void pop() {
Node* temp;
if (top_node != NULL) {
temp = top_node;
top_node = top_node->next;
delete temp;
--node_num;
}
}
void swap(Stack & stack) {
size_t temp = node_num;
node_num = stack.node_num;
stack.node_num = temp;
Node* t = top_node;
top_node = stack.top_node;
stack.top_node = t;
}
void reverse() {
// 利用中间栈的做法
// if (node_num <= 1) return;
// Stack temp;
// Node* p = top_node;
// while (p) {
// temp.push(p->element);
// p = p->next;
// }
// swap(temp); // 巧
// 直接用指针实现,不用中间栈的情况,这种实现方法更好也更加复杂
if (node_num <= 1) return;
Node* newtop = top_node;
Node* t = top_node->next;
newtop->next = NULL;
while (t != NULL) {
top_node = t;
t = top_node->next;
top_node->next = newtop;
newtop = top_node;
}
top_node = newtop;
// 下面的代码让我调试了几个小时始终找不出错误[事实证明我确实错了]
// 注意透彻理解指针变动的过程
// if (node_num <= 1) return;
// Node* newtop = top_node;
// newtop->next = NULL;
// Node* t = top_node->next;
// while (t != NULL) {
// top_node = t;
// t = top_node->next;
// top_node->next = newtop;
// newtop = top_node;
// }
// top_node = newtop;
}
void clear() {
if (top_node != NULL) {
Node* p = top_node;
while (p) {
Node* temp = p;
p = p->next;
delete temp;
}
}
top_node = NULL;
node_num = 0;
}
};
#endif
重要代码段:
if (node_num <= 1) return;
Node* newtop = top_node;
Node* t = top_node->next;
newtop->next = NULL;
while (t != NULL) {
top_node = t;
t = top_node->next;
top_node->next = newtop;
newtop = top_node;
}
top_node = newtop;
1 swap中直接进行指针的交换,这就充分体现了指针的优势,不需要进行内存的复制粘贴,只需要交换指向内存的指针
2.clear 的另外一种实现方法:
void clear() {
if (empty()) return;
while (!empty())
pop();
top_node = NULL;
node_num = 0;
}
3. element(ele) 直接调用拷贝构造函数,例如: stack.push(Job(1)), 首先Job(1)调用构造函数创建了一个新的对象, 若使用element = ele; 则此时首先创建一个临时对象,然后调用拷贝构造函数,所以总共创建了两次. 若使用element(ele),则直接调用拷贝构造函数,总共创建了一次, 注意两者之间的不同,这也是为什么使用初始化列表比使用=好的原因.