Carl 语录
把常用的函数抽象出来,形成自己的工具库。而不要每次都cv修修改改。
可以看出peek()的实现,直接复用了pop(), 要不然,对stOut判空的逻辑又要重写一遍。
1.问题:再多说一些代码开发上的习惯问题,在工业级别代码开发中,最忌讳的就是 实现一个类似的函数,直接把代码粘过来改一改就完事了。 这样的项目代码会越来越乱,一定要懂得复用,功能相近的函数要抽象出来,不要大量的复制粘贴,很容易出问题!(踩过坑的人自然懂)
2.建议:工作中如果发现某一个功能自己要经常用,同事们可能也会用到,自己就花点时间把这个功能抽象成一个好用的函数或者工具类,不仅自己方便,也方便了同事们。
3.益处:同事们就会逐渐认可你的工作态度和工作能力,自己的口碑都是这么一点一点积累起来的!在同事圈里口碑起来了之后,你就发现自己走上了一个正循环,以后的升职加薪才少不了你!
2. 用栈实现队列
一刷无思路
232. 用栈实现队列
实现目标:
先入后出 =》先入先出
思路:
- 先入后出 即 取出顺序与放入顺序相反,故两次 “先入后出” 之后,可实现“先入先出”。即将元素放入栈后,再将元素放入第二个栈内,此时从后者中取出元素,即从整体上看遵循“先入先出”。
实现过程:
-
一个输入栈stIn;push() 将队列元素放入此栈。由于栈是先入后出的,故先放入的元素在栈底。
-
一个输出栈stOut:pop() 若栈为空,则将 stIn 中元素全部取入stOut,由于栈是先入后出的,故此时先放入的元素在栈顶
代码
class MyQueue {
public:
stack<int> stIn;
stack<int> stOut;
MyQueue() {
}
void push(int x) {
stIn.push(x);
}
int pop() {
if(stOut.empty()){
while(!stIn.empty()){
stOut.push(stIn.top());
stIn.pop();
}
}
int result = stOut.top(); // 取出后删除此元素。但栈的pop()并不返回元素,需要提前用变量存储
stOut.pop();
return result;
}
int peek() {
if(stOut.empty()){ //判空。若输出栈不为空则从stOut顶部取元素;若为空,则需要从stIn中取至栈底元素。
while(!stIn.empty()){
stOut.push(stIn.top());
stIn.pop();
}
}
return stOut.top();
// int result = this->pop(); // 该数据结构没有 直接取顶部top而不删去top 的函数。复用方法有利于软件工程化
// stOut.push(result);
}
bool empty() {
return stOut.empty() && stIn.empty();
}
};
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue* obj = new MyQueue();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->peek();
* bool param_4 = obj->empty();
*/
3. 用队列实现栈
实现目标
先入先出=》后入先出:每次取出的都是当前最后放入的元素。
思路
- 用一个队列实现栈: 那么每次取出时,将所有元素放置于最后一个元素的后面即可。
- 用两个队列实现栈: 那么每次取出时,将一个队列中除最后一个元素外全部放入另一个队列中,再取出前者中的元素即可。
实现过程
-
Carl 的实现是只将所有元素放在que1,每次 “出栈” ——
1)将que1中除队尾元素外全部转入que2中;
2)取出 que1 队尾元素;
3)再从que2倒回que1,每次 “出栈” 要转移两次。 -
我认为这个过程比较耗时,故加入判定,
1)哪个不为空就从那个队列倒入另一个队列;
2)取出 该队列 队尾元素,每次 “出栈” 只转移一次。
代码
- 用两个队列实现栈:(元素在两个队列之间来回倒)
class MyStack {
public:
//元素在两个队列来回倒
queue<int> que1;
queue<int> que2;
MyStack() {
}
void push(int x) {
if(que1.empty()) que2.push(x); //que1为空则说明元素都在que2中
else que1.push(x);
}
int pop() {
// 如果栈为空,则返回null
if(this->empty()) return -1;
//如果que1为空,则说明元素都在que2
if(que1.empty()){
// 当que2有多个元素时,将除队列尾部外的所有元素转移到que1
while(que2.size() > 1){
que1.push(que2.front());
que2.pop();
}
//当que2中只有1个元素时,返回该元素,并从que2中删除
int result = que2.front();
que2.pop();
return result;
}
//如果que1不为空,则说明元素都在que1
//当que1有多个元素时,将除队列尾部外的所有元素转移到que2
while(que1.size() > 1){
que2.push(que1.front());
que1.pop();
}
//当que1中只有1个元素时,返回该元素,并从que1中删除
int result = que1.front();
que1.pop();
return result;
}
int top() {
//复用函数
int result = this->pop(); // 保存栈顶元素
this->push(result); //重新放回
return result;
}
bool empty() {
return (que1.empty() && que2.empty());
}
};
/**
* Your MyStack object will be instantiated and called as such:
* MyStack* obj = new MyStack();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->top();
* bool param_4 = obj->empty();
*/