首页 > 技术文章 > 第三十五课 栈的概念及实现(下)

wanmeishenghuo 2018-09-16 19:37 原文

 

自定义Test类,给出如下的测试程序:

 1 #include <iostream>
 2 #include "StaticStack.h"
 3 
 4 using namespace std;
 5 using namespace DTLib;
 6 
 7 class Test : public Object
 8 {
 9 public:
10     Test()
11     {
12         cout << "Test()" << endl;
13     }
14 
15     ~Test()
16     {
17         cout << "~Test()" << endl;
18     }
19 };
20 
21 int main()
22 {
23     StaticStack<Test, 10> stack;
24 
25     cout << stack.size() << endl;
26 
27     return 0;
28 }

运行结果如下:

 

 此时栈中没有任何元素,却调用了10次构造函数和10次析构函数。

这是因为我们使用了原生数组作为存储空间,在创建栈的时候,当然会调用泛指类型T的构造函数。

我们需要另一种存储形式,来避免这种缺陷。

 

 

 添加LinkStack.h文件:

 1 #ifndef LINKSTACK_H
 2 #define LINKSTACK_H
 3 
 4 #include "Stack.h"
 5 #include "LinkList.h"
 6 
 7 
 8 namespace DTLib
 9 {
10 
11 template < typename T >
12 class LinkStack : public Stack<T>
13 {
14 protected:
15     LinkList<T> m_list;
16 public:
17     void push(const T& e)
18     {
19         m_list.insert(0, e);
20     }
21 
22     void pop()
23     {
24         if( m_list.length() > 0 )
25         {
26             m_list.remove(0);
27         }
28         else
29         {
30             THROW_EXCEPTION(InvalidOperationException, "No element in current stack...");
31         }
32     }
33 
34     T top() const
35     {
36         if( m_list.length() > 0 )
37         {
38             return m_list.get(0);
39         }
40         else
41         {
42             THROW_EXCEPTION(InvalidOperationException, "No element in current stack...");
43         }
44     }
45 
46     void clear()
47     {
48         m_list.clear();
49     }
50 
51     int size() const
52     {
53         return m_list.length();
54     }
55 
56 };
57 
58 }
59 
60 #endif // LINKSTACK_H

测试程序如下:

 1 #include <iostream>
 2 #include "LinkStack.h"
 3 
 4 using namespace std;
 5 using namespace DTLib;
 6 
 7 class Test : public Object
 8 {
 9 public:
10     Test()
11     {
12         cout << "Test()" << endl;
13     }
14 
15     ~Test()
16     {
17         cout << "~Test()" << endl;
18     }
19 };
20 
21 int main()
22 {
23     LinkStack<Test> stack;
24 
25     cout << stack.size() << endl;
26 
27     return 0;
28 }

 

结果如下:

没有再调用构造函数。

 

栈的应用实践:

 

 问题:

如何实现编译器中的符号成对检测?

 

程序如下:

 1 #include <iostream>
 2 #include "LinkStack.h"
 3 
 4 using namespace std;
 5 using namespace DTLib;
 6 
 7 bool is_left(char c)
 8 {
 9     return (c == '(') || (c == '{') || (c == '[') || (c == '<');
10 }
11 
12 bool is_right(char c)
13 {
14     return (c == ')') || (c == '}') || (c == ']') || (c == '>');
15 }
16 
17 bool is_quot(char c)
18 {
19     return (c == '\'') || (c == '\"');
20 }
21 
22 bool is_match(char l, char r)
23 {
24     return ( (l == '(') && (r == ')') ) ||
25             ( (l == '{') && (r == '}') ) ||
26             ( (l == '[') && (r == ']') ) ||
27             ( (l == '<') && (r == '>') ) ||
28             ( (l == '\'') && (r == '\'') ) ||
29             ( (l == '\"') && (r == '\"') );
30 }
31 
32 bool scan(const char* code)
33 {
34     LinkStack<char> stack;
35     int i = 0;
36     bool ret = true;
37 
38     code = (code == NULL) ? "" : code;
39 
40     while( ret && (code[i] != '\0') )
41     {
42         if( is_left(code[i]) )
43         {
44             stack.push(code[i]);
45         }
46         else if( is_right(code[i]) )
47         {
48             //右字符且此时栈大小为0(即认为不匹配),则匹配失败
49             if( (stack.size() > 0) && is_match(stack.top(), code[i]) )
50             {
51                 stack.pop();
52             }
53             else
54             {
55                 ret = false;
56             }
57         }
58         else if( is_quot(code[i]) )  // 引号单独处理
59         {
60             //如果栈是空的或者当前的引号是左字符(也就是和栈顶不匹配),则入栈
61             if( stack.size() == 0 || !is_match(stack.top(), code[i]) )
62             {
63                 stack.push( code[i] );
64             }
65             else if( is_match(stack.top(), code[i]) ) //如果匹配,则栈顶出栈
66             {
67                 stack.pop();
68             }
69         }
70 
71         i++;
72     }
73 
74     return ret && (stack.size() == 0);
75 }
76 
77 int main()
78 {
79     cout << scan("<a{b(\'x\')c}d>") << endl;
80 
81     return 0;
82 }

结果如下:

测试程序2:

 1 #include <iostream>
 2 #include "LinkStack.h"
 3 
 4 using namespace std;
 5 using namespace DTLib;
 6 
 7 bool is_left(char c)
 8 {
 9     return (c == '(') || (c == '{') || (c == '[') || (c == '<');
10 }
11 
12 bool is_right(char c)
13 {
14     return (c == ')') || (c == '}') || (c == ']') || (c == '>');
15 }
16 
17 bool is_quot(char c)
18 {
19     return (c == '\'') || (c == '\"');
20 }
21 
22 bool is_match(char l, char r)
23 {
24     return ( (l == '(') && (r == ')') ) ||
25             ( (l == '{') && (r == '}') ) ||
26             ( (l == '[') && (r == ']') ) ||
27             ( (l == '<') && (r == '>') ) ||
28             ( (l == '\'') && (r == '\'') ) ||
29             ( (l == '\"') && (r == '\"') );
30 }
31 
32 bool scan(const char* code)
33 {
34     LinkStack<char> stack;
35     int i = 0;
36     bool ret = true;
37 
38     code = (code == NULL) ? "" : code;
39 
40     while( ret && (code[i] != '\0') )
41     {
42         if( is_left(code[i]) )
43         {
44             stack.push(code[i]);
45         }
46         else if( is_right(code[i]) )
47         {
48             //右字符且此时栈大小为0(即认为不匹配),则匹配失败
49             if( (stack.size() > 0) && is_match(stack.top(), code[i]) )
50             {
51                 stack.pop();
52             }
53             else
54             {
55                 ret = false;
56             }
57         }
58         else if( is_quot(code[i]) )  // 引号单独处理
59         {
60             //如果栈是空的或者当前的引号是左字符(也就是和栈顶不匹配),则入栈
61             if( stack.size() == 0 || !is_match(stack.top(), code[i]) )
62             {
63                 stack.push( code[i] );
64             }
65             else if( is_match(stack.top(), code[i]) ) //如果匹配,则栈顶出栈
66             {
67                 stack.pop();
68             }
69         }
70 
71         i++;
72     }
73 
74     return ret && (stack.size() == 0);
75 }
76 
77 int main()
78 {
79     cout << scan("else if( is_quot(code[i]) ){if( stack.size() == 0 || \
80                  !is_match(stack.top(), code[i]) ) {stack.push( code[i] ); \
81                   }else if( is_match(stack.top(), code[i]) ){stack.pop();}}" \
82                 ) << endl;
83 
84     return 0;
85 }

我们测试的是一段C++的代码,结果依然输出1。

 

小结:

 

推荐阅读