C++ stack

来源:互联网 发布:端口定义 编辑:程序博客网 时间:2024/05/24 05:32
如果你和程序员接触的比较多,你可能会经常听到他们说一个词——“栈溢出(Stack Overflow)”。那么栈到底是什么?为什么会溢出这?下面我们就一一解答这些问题。一点点题外话,Stack Overflow 也是一个很好的社区。


栈(stack),又名堆栈,是一种运算受限制的线性表类型的数据结构。其限制是只允许在栈的一端进行插入和删除运算。这一端被成为栈顶,相对地,把另一端称为栈底。


可以想象往子弹夹中装子弹的情形,正常情况下只能往子弹夹入口那段端入子弹,这一步就好比向栈中压入元素,称为push,射击的时候,弹夹会从顶端弹出子弹,这一步就好比从栈顶弹出元素,称为pop,可以发现,从栈顶弹出的子弹是最后一个压进去的子弹,这也是栈的一个重要性质,先进后出(FILO——first in last out)。另外,用一个top指针来标示当前栈顶的位置。
关于栈的实现,一种方法是利用数组手动实现,需要固定缓存大小,也是就是数组大小。




1
int stack[maxsize], top = 0;
2
void push(int x) {
3
    stack[top++] = x;
4
}
5
void pop() {
6
   --top;
7
}
8
int topval() {
9
    return stack[top - 1];
10
}
11
int empty() {
12
    return top > 0;
13
}
用stack表示储存栈的空间,top表示当栈顶的指针位置,方法push()压入一个数x到栈顶,方法pop()从栈顶弹出一个元素,方法topval()获取栈顶元素。
在 C++ 和 Java 中有已经写好的栈对象,可以直接用。C 语言中没有对象的概念,但是使用 C 语言的同学有必要学习一下,C++ 是兼容 C 语言的,学会使用 STL 的好处第一是避免自己写的有错误,第二是节省时间。




1
#include <stack>
2
#include <iostream>
3
using namepsace std;
4
stack<int> S;
5
int main() {
6
    S.push(1);
7
    S.push(10);
8
    S.push(7);
9
    while (!S.empty()) {
10
        cout << S.top() << endl;
11
        S.pop();
12
    }
13


递归是计算机编程中应用最广泛的一个技巧,也是比较难理解的一个技巧,所以我们打算在这章花大量的时间来理解递归。所谓递归,就是函数调用函数自身 ,一个过程或者函数在其定义或说明中有直接或者间接调用自身都叫递归。而递归一般都用来解决有重复子问题的问题。


我们先来理解直接递归,间接递归非常复杂,用的比较少。下面通过求解 n!(! 代表阶乘)的问题来理解直接递归。




1
int factorial(int n) {
2
    return n * factorial(n - 1);
3
}
我们定义int factorial(int n)函数的功能是返回 n!。如果你在心里模拟一遍 factorial(1) 的运行过程,你会发现函数好像会无限的调用下去。这样引申出递归一个难点——边界条件。所谓边界条件,就是什么情况下,函数不应该再继续调用自身了。那么很显然,按照阶乘的定义factorial函数对应的边界条件是n == 1,如果n == 1,函数应该立即返回。




1
int factorial(int n) {
2
    if (n == 1) {
3
        return 1;
4
    }
5
    return n * factorial(n - 1);
6
}
为了更通俗易懂的理解,看下面这段代码。




1
int factorial_1() {
2
    return 1;
3
}
4
int factorial_2() {
5
    return 2 * factorial_1();
6
}
7
int factorial_3() {
8
    return 3 * factorial_2();
9
}
调用factorial(3)和factorial_3()会得到同样的结果。你会发现,factorial(3)递归的过程和factorial_3()调用的过程是一模一样,只是 factorial(3)调用的是自己,这也就是所谓的递归。factorial_2()相当于调用 factorial(2)。如果你调用的n更大, 你会发现,写出的 factorial_n() 都具有一样的形式,所以我们能只写一个函数,然后自己调用自己,实现递归。


阶乘问题递归形式看起来比较简单,接下里我们看另外一个复杂一点的问题。
Fibonacci数列的定义是


\displaystyle f(n)=\begin{cases}1 & n = 1 \\1 & n = 2 \\f(n - 1) + f(n - 2) & n > 2\end{cases}f(n)=
​​ 
​1                            ​n=1
​1                            n=2
​f(n−1)+f(n−2)      ​n>2
​​ 



如果用递归写 Fibonacci 数列,其实按照定义可以很简单的写出来。




1
int fib(int n) {
2
    if (n == 1 || n == 2) {
3
        return 1;
4
    }
5
    return fib(n - 1) + fib(n - 2);
6

}



    return 0;
14
}
上面代码是 C++ 里面的 stack 的用法。push,pop分别是压栈和出栈,top是栈顶元素,empty判断栈是否为空。

0 0
原创粉丝点击