算法学习笔记005——栈及应用

算法学习笔记005——栈及应用

栈(stack)是一种实现后进先出(last-in, first out; LIFO)的容器。它是一种线性结构,当和向量、链表等线性数据结构不同的是,栈仅允许在一端进行操作:插入和删除。允许操作的一端成为栈顶(top),另一端就是栈低(bottom)。

栈(stack)是一种很重要的数据结构,用途也很广泛,如:表达式计算,函数调用的现场保护,递归调用所需要的递归工作栈等等都是基于栈这种数据结构。(除此之外还有很多应用)。

栈(stack)在C++标准模板库(STL)中实现了,以下是栈(stack)容器中的一些操作:

复制代码
 1 template <class T>
 2 class stack
 3 {
 4 public:
 5     stack();
 6     stack(const stack&);
 7     ~stack();
 8     stack& operator =(const stack&);
 9     int size() const;
10     bool empty() const;
11     int &top();
12     void push(const int&);
13     void pop();
14     //..
15 };
复制代码

在上面模板中可以看到,栈的主要操作有进栈(push),出栈(pop),取栈顶元素(top)和判断栈是否为空(empty)。

关于在如何使用STL中的栈结构,请参考www.cplusplus.com,那里有标准库所有容器的用法。

以下讨论两个栈的应用:

RPN计算器(RPN calculator)

RNP计算器是一种处理后缀表达式的计算器,其工作原理是,

1)输入的符号是一个数就压入栈(stack),

2)输入的是运算符就将栈顶的两元素弹出来进行计算,并把计算计算结果压入栈;

3)重复1),2)步骤,直到退出。

例如,3*(4+5)的后缀表示法是3 4 5 + *,按后缀表示法的顺序输入,就会得到27. 具体的实现

进制转换

日常我们都使用十进制来计算,但是在计算机中,十进制在很多时候是行不通的,必须进行进制转换,这也是学习程序设计的必修内容。

进制转换算法:

1、输入十进制整数N,基数B;

2、用B除N,将余数N%B压入栈,然后用商N/B代替N;

3、N/B为0结束,不为0就转到2。

此外还有:中缀表达式转后缀表达式,括号配对问题,调度问题也可以利用栈结构来解决。在ChinaUNIX的一个博客GP-King中有详细叙述。想了解可以去看看。

以下附上两个应用代码:

View Code
1 //RPN计算器
 2 #include<iostream>
 3 #include<stack>
 4 #include<string>
 5 #include<sstream>
 6 using namespace std;
 7 
 8 int main()
 9 {
10     stack<char> oprtr;
11     stack<double> oprnd;
12     string input;
13     bool quit = false;
14     double x,y;
15     while(!quit)
16     {
17         cout<<"RPN> ";
18         cin>>input;
19         switch(input[0])
20         {
21         case 'Q':
22         case 'q':
23             quit = true;
24             break;
25         case '+':
26             y=oprnd.top();
27             oprnd.pop();
28             x=oprnd.top();
29             oprnd.pop();
30             cout<<"\t"<<x<<" + "<<y<<" = "<<x+y<<endl;
31             oprnd.push(x+y);
32             break;
33         case '-':
34             y=oprnd.top();
35             oprnd.pop();
36             x=oprnd.top();
37             oprnd.pop();
38             cout<<"\t"<<x<<" - "<<y<<" = "<<x-y<<endl;
39             oprnd.push(x-y);
40             break;
41         case '*':
42             y=oprnd.top();
43             oprnd.pop();
44             x=oprnd.top();
45             oprnd.pop();
46             cout<<"\t"<<x<<" * "<<y<<" = "<<x*y<<endl;
47             oprnd.push(x*y);
48             break;
49         case '/':
50             y=oprnd.top();
51             oprnd.pop();
52             x=oprnd.top();
53             oprnd.pop();
54             cout<<"\t"<<x<<" / "<<y<<" = "<<x/y<<endl;
55             oprnd.push(x/y);
56             break;
57         case 'c':
58         case 'C':
59             while(!oprnd.empty())
60                 oprnd.pop();
61             cout<<"Clear...\n";
62             break;
63         default:
64             istringstream in(input);
65             in>>x;
66             oprnd.push(x);
67         }
68     }
69     return 0;
70 }
View Code
 1 #include<iostream>
 2 #include<string>
 3 #include<stack>
 4 using namespace std;
 5 
 6 string dec2base(int num, int base)
 7 {
 8     string digitChar = "0123456789ABCDEF",numStr = "";
 9     stack<char> stk;
10     do{
11         stk.push(digitChar[num%base]);
12         num/=base;
13     }while(num!=0);
14 
15     while(!stk.empty())
16     {
17         numStr+=stk.top();
18         stk.pop();
19     }
20     return numStr;
21 }
22 
23 int main()
24 {
25     int num,base;
26     cout<<"Enter a number: "; cin>>num;
27     cout<<"Enter a number as base: "; cin>>base;
28     string s = dec2base(num,base);
29     cout<<s<<endl;
30     return 0;
31 }

C/C++

 
摘要: 栈(stack)是一种实现后进先出(last-in, first out; LIFO)的容器。它是一种线性结构,当和向量、链表等线性数据结构不同的是,栈仅允许在一端进行操作:插入和删除。允许操作的一端成为栈顶(top),另一端就是栈低(bottom)。栈(stack)是一种很重要的数据结构,用途也很广泛,如:表达式计算,函数调用的现场保护,递归调用所需要的递归工作栈等等都是基于栈这种数据结构。(除此之外还有很多应用)。栈(stack)在C++标准模板库(STL)中实现了,以下是栈(stack)容器中的一些操作: 1 template <class T> 2 class stack 阅读全文
posted @ 2013-04-11 16:27 Sprout 阅读(111) | 评论 (0) 编辑
摘要: 堆(本文指的是二叉堆),具有两个性质:1、结构性质;2、堆序性质。结构性:堆是一棵完全二叉树,即堆是一棵完全被填满的二叉树,底层元素从左到右依次填入。基于结构这样的结构性,堆可以直接使用数组来构建。如下图:而且在数组中很容易知道:对于数组中任意 i 位置上的元素,其左儿子在2i上,右儿子在2i+1上,而父亲则在[i/2](向下取整)。堆序性:在堆中(如上图的最大堆)对于任意节点X,X的父亲节点的值不小于X节点中的值,而X节点的值比左右儿子节点的值都要大。堆因为具有堆序性,其主要应用是优先队列(priority queue)。关于堆的详细介绍:WiKi一个具有n个元素的堆是基于一棵完全二叉树,故阅读全文
posted @ 2013-03-26 16:31 Sprout 阅读(62) | 评论 (0) 编辑
摘要: 谢尔排序(Shell Sort),也被称为缩减增量排序(Diminishing increment sort)。顾名思义,应该可以想到谢尔排序的原理——缩减增量。谢尔排序(Shell Sort)的原理是:通过比较相距一定距离的元素进行排序,比较所用的距离逐渐减小,直到比较相邻的元素。很显然,这个原理和插入排序(Insertion Sort)的原理是相似的,插入排序(Insertion Sort)只不过是通过比较相邻元素进行排序。有了插入排序(Insertion Sort)作为基础,谢尔排序(Shell Sort)的算法很简单地就可以给出来了。每次进行谢尔排序之后的结果初始状态 81 9...阅读全文
posted @ 2013-03-22 21:52 Sprout 阅读(25) | 评论 (0) 编辑
摘要: 最近本人在网易上看“麻省理工学院公开课:算法导论”,现在才开始看到第六集“顺序统计、中值”。也正好配合此前已购买好的算法参考书——《算法导论》(Introduction to Algorithms)第二版。由于上学期已经学过算法设计与分析的课程,目前看视频和自己啃书的效果还是不错的,对于每个算法的理解也和此前大为不同。重新注册了Blog,用于记录自己人点点滴滴。对于排序算法,相信每个接触过算法的人来说一定不会感到陌生,而且很多人可以顺手拈来得写几个排序算法。就我们熟知的排序算法就有差不多十几种吧,以下列举一些本人已经接触过的排序算法并且在文章后面也会写到各个排序算法的实现和复杂度分析。首先,插阅读全文
posted @ 2013-03-12 13:07 Sprout 阅读(32) | 评论 (0) 编辑
梦之所寄,行之所为,地狱之门为之洞开!
 
原文地址:https://www.cnblogs.com/Leo_wl/p/3014879.html