栈的链表实现,以及编译原理中的括号匹配
2010-08-07 17:06
447 查看
一:
编译原理常有括号的匹配算法。用数组和链表实现的栈都可以实现。现用链表吧。
代码:
cyq@cyq-desktop:~/桌面/C$ cat LinkStack2.c
#include <iostream>
#include <cstdlib>
#include <assert.h>
using namespace std;
class LinkStackNode {
public:
char data;
LinkStackNode* link;
LinkStackNode(char& value):link(NULL),data(value){}
};
class LinkStack{
LinkStackNode* head;
public:
LinkStack():head(NULL){}
void Push(char& value);
char& GetTop();
char Pop();
bool IsEmpty();
void MakeEmpty();
};
void LinkStack::Push(char& value)
{
LinkStackNode* add= new LinkStackNode(value);
add->link= head;
head=add;
}
char& LinkStack::GetTop()
{
return head->data;
}
char LinkStack::Pop()
{
assert(head!=NULL);
LinkStackNode* old = head;
head = head->link;
char data=old->data;
delete old;
return data;
}
bool LinkStack::IsEmpty()
{
return
head==NULL;
}
void LinkStack::MakeEmpty()
{
while(!this->IsEmpty())
{
this->Pop();
}
}
int main(int argc , char *argv[])
{
cout<<"输入括号序列(以为@结束标志):"<<endl;
LinkStack small;
char a;
while(cin.peek()!='@'){
cin>>a;
switch(a)
{
case '(': small.Push(a) ;break;
case ')':
if(!small.IsEmpty())
{
small.Pop(); break;
}
if(small.IsEmpty())
{
cout<<"匹配失败!"<<endl;
exit(0);
break;
}
}
};
if(small.IsEmpty())
cout<<"匹配成功!"<<endl;
else
cout<<"匹配失败!"<<endl;
return 0;
}
二:编译并运行:
cyq@cyq-desktop:~/桌面/C$ g++ LinkStack2.c -o LinkStack2 && ./LinkStack2
输入括号序列(以为@结束标志):
longxibendi(()) (longxibendi)@
匹配成功!
cyq@cyq-desktop:~/桌面/C$ ./LinkStack2
输入括号序列(以为@结束标志):
(longxibendi@126.com)
匹配失败!
三:代码分析:
一共用了两个类,一个节点类,一个栈类。
节点类是:LinkStackNode
栈类是:LinkStack
如果链表会的话,这个程序很简单。就解释以下部分:
1. while(cin.peek()!='@')
使用peek方法,接收一个字符,如果是@则停止接收。
2. this
成员函数具有一个附加的隐含行参,即指向该类对象的一个指针。这个隐含行参命民为this,与调用成员函数的对象绑定在一起。成员函数的函数体可以显示的使用this指针。但不是必须这么做。所以:我在程序中,IsEmpty()使用了this .
void LinkStack::MakeEmpty()
{
while(!this->IsEmpty())
{
this->Pop();
}
}
如果不理解,就直接理解为对象的指针好了。而在定义函数时,还没有对象(是在类中定义函数),所以没法使用对象。但这时可以使用this来代替。
具体可以参考:http://topic.csdn.net/u/20070306/22/81af1a98-6633-4be4-9690-59575f42ee3a.html
也可以看《C++ Primer》 第四版 376页
3. assert(head!=NULL);
assert(),如果括号内的条件满足,程序就往下执行,否则,程序终止
使用这个函数,需要包含头文件assert.h
四:代码扩充
使用fstream,打开读取文件
如果喜欢的话,可以用open,从文本读入数据,然后再匹配。
1.比如可以这样写
cyq@cyq-desktop:~/桌面/C$ cat LinkStack3.c
#include <iostream>
#include <cstdlib>
#include <assert.h>
#include <fstream>
using namespace std;
class LinkStackNode {
public:
char data;
LinkStackNode* link;
LinkStackNode(char& value):link(NULL),data(value){}
};
class LinkStack{
LinkStackNode* head;
public:
LinkStack():head(NULL){}
void Push(char& value);
char& GetTop();
char Pop();
bool IsEmpty();
void MakeEmpty();
};
void LinkStack::Push(char& value)
{
LinkStackNode* add= new LinkStackNode(value);
add->link= head;
head=add;
}
char& LinkStack::GetTop()
{
return head->data;
}
char LinkStack::Pop()
{
assert(head!=NULL);
LinkStackNode* old = head;
head = head->link;
char data=old->data;
delete old;
return data;
}
bool LinkStack::IsEmpty()
{
return
head==NULL;
}
/*
void LinkStack::MakeEmpty()
{
while(!this->IsEmpty())
{
this->Pop();
}
}
*/
int main(int argc , char *argv[])
{
cout<<"输入括号序列(以为@结束标志):"<<endl;
LinkStack small;
char a;
ifstream inf;
inf.open("test.txt");
if(!inf)
{ cerr<<"Error! Open fault!"<<endl;
return 0 ;
}
while(inf >>a)
{
if(a=='@')
break;
switch(a)
{
case '(': small.Push(a) ;break;
case ')':
if(!small.IsEmpty())
{
small.Pop(); break;
}
if(small.IsEmpty())
{
cout<<"匹配失败!"<<endl;
exit(0);
break;
}
}
};
inf.close();
if(small.IsEmpty())
cout<<"匹配成功!"<<endl;
else
cout<<"匹配失败!"<<endl;
return 0;
}
2.test.txt 内容如下:
cyq@cyq-desktop:~/桌面/C$ cat test.txt
#include <iostream>
main
( )
(000)
longxibendi@126.com
http://blog.csdn.net/longxibendi
3.编译运行:
cyq@cyq-desktop:~/桌面/C$ g++ LinkStack3.c -o LinkStack3 && ./LinkStack3
输入括号序列(以为@结束标志):
匹配成功!
五:总结:
这个程序编译器中用到了。结合以前学过的this,assert,peek,open来灵活运用栈。顺便复习以下以前的知识了。
声明:本文档可以随意更改,但必须署名原作者
作者:凤凰舞者 qq:578989855
编译原理常有括号的匹配算法。用数组和链表实现的栈都可以实现。现用链表吧。
代码:
cyq@cyq-desktop:~/桌面/C$ cat LinkStack2.c
#include <iostream>
#include <cstdlib>
#include <assert.h>
using namespace std;
class LinkStackNode {
public:
char data;
LinkStackNode* link;
LinkStackNode(char& value):link(NULL),data(value){}
};
class LinkStack{
LinkStackNode* head;
public:
LinkStack():head(NULL){}
void Push(char& value);
char& GetTop();
char Pop();
bool IsEmpty();
void MakeEmpty();
};
void LinkStack::Push(char& value)
{
LinkStackNode* add= new LinkStackNode(value);
add->link= head;
head=add;
}
char& LinkStack::GetTop()
{
return head->data;
}
char LinkStack::Pop()
{
assert(head!=NULL);
LinkStackNode* old = head;
head = head->link;
char data=old->data;
delete old;
return data;
}
bool LinkStack::IsEmpty()
{
return
head==NULL;
}
void LinkStack::MakeEmpty()
{
while(!this->IsEmpty())
{
this->Pop();
}
}
int main(int argc , char *argv[])
{
cout<<"输入括号序列(以为@结束标志):"<<endl;
LinkStack small;
char a;
while(cin.peek()!='@'){
cin>>a;
switch(a)
{
case '(': small.Push(a) ;break;
case ')':
if(!small.IsEmpty())
{
small.Pop(); break;
}
if(small.IsEmpty())
{
cout<<"匹配失败!"<<endl;
exit(0);
break;
}
}
};
if(small.IsEmpty())
cout<<"匹配成功!"<<endl;
else
cout<<"匹配失败!"<<endl;
return 0;
}
二:编译并运行:
cyq@cyq-desktop:~/桌面/C$ g++ LinkStack2.c -o LinkStack2 && ./LinkStack2
输入括号序列(以为@结束标志):
longxibendi(()) (longxibendi)@
匹配成功!
cyq@cyq-desktop:~/桌面/C$ ./LinkStack2
输入括号序列(以为@结束标志):
(longxibendi@126.com)
匹配失败!
三:代码分析:
一共用了两个类,一个节点类,一个栈类。
节点类是:LinkStackNode
栈类是:LinkStack
如果链表会的话,这个程序很简单。就解释以下部分:
1. while(cin.peek()!='@')
使用peek方法,接收一个字符,如果是@则停止接收。
2. this
成员函数具有一个附加的隐含行参,即指向该类对象的一个指针。这个隐含行参命民为this,与调用成员函数的对象绑定在一起。成员函数的函数体可以显示的使用this指针。但不是必须这么做。所以:我在程序中,IsEmpty()使用了this .
void LinkStack::MakeEmpty()
{
while(!this->IsEmpty())
{
this->Pop();
}
}
如果不理解,就直接理解为对象的指针好了。而在定义函数时,还没有对象(是在类中定义函数),所以没法使用对象。但这时可以使用this来代替。
具体可以参考:http://topic.csdn.net/u/20070306/22/81af1a98-6633-4be4-9690-59575f42ee3a.html
也可以看《C++ Primer》 第四版 376页
3. assert(head!=NULL);
assert(),如果括号内的条件满足,程序就往下执行,否则,程序终止
使用这个函数,需要包含头文件assert.h
四:代码扩充
使用fstream,打开读取文件
如果喜欢的话,可以用open,从文本读入数据,然后再匹配。
1.比如可以这样写
cyq@cyq-desktop:~/桌面/C$ cat LinkStack3.c
#include <iostream>
#include <cstdlib>
#include <assert.h>
#include <fstream>
using namespace std;
class LinkStackNode {
public:
char data;
LinkStackNode* link;
LinkStackNode(char& value):link(NULL),data(value){}
};
class LinkStack{
LinkStackNode* head;
public:
LinkStack():head(NULL){}
void Push(char& value);
char& GetTop();
char Pop();
bool IsEmpty();
void MakeEmpty();
};
void LinkStack::Push(char& value)
{
LinkStackNode* add= new LinkStackNode(value);
add->link= head;
head=add;
}
char& LinkStack::GetTop()
{
return head->data;
}
char LinkStack::Pop()
{
assert(head!=NULL);
LinkStackNode* old = head;
head = head->link;
char data=old->data;
delete old;
return data;
}
bool LinkStack::IsEmpty()
{
return
head==NULL;
}
/*
void LinkStack::MakeEmpty()
{
while(!this->IsEmpty())
{
this->Pop();
}
}
*/
int main(int argc , char *argv[])
{
cout<<"输入括号序列(以为@结束标志):"<<endl;
LinkStack small;
char a;
ifstream inf;
inf.open("test.txt");
if(!inf)
{ cerr<<"Error! Open fault!"<<endl;
return 0 ;
}
while(inf >>a)
{
if(a=='@')
break;
switch(a)
{
case '(': small.Push(a) ;break;
case ')':
if(!small.IsEmpty())
{
small.Pop(); break;
}
if(small.IsEmpty())
{
cout<<"匹配失败!"<<endl;
exit(0);
break;
}
}
};
inf.close();
if(small.IsEmpty())
cout<<"匹配成功!"<<endl;
else
cout<<"匹配失败!"<<endl;
return 0;
}
2.test.txt 内容如下:
cyq@cyq-desktop:~/桌面/C$ cat test.txt
#include <iostream>
main
( )
(000)
longxibendi@126.com
http://blog.csdn.net/longxibendi
3.编译运行:
cyq@cyq-desktop:~/桌面/C$ g++ LinkStack3.c -o LinkStack3 && ./LinkStack3
输入括号序列(以为@结束标志):
匹配成功!
五:总结:
这个程序编译器中用到了。结合以前学过的this,assert,peek,open来灵活运用栈。顺便复习以下以前的知识了。
声明:本文档可以随意更改,但必须署名原作者
作者:凤凰舞者 qq:578989855
相关文章推荐
- 正则表达式实现——匹配括号中的A 以及 匹配非括号中的A
- C++函数重载实现的原理以及为什么在C++中调用C语言编译的函数时要加上extern "C"声明
- 数据结构(1)——顺序栈的实现,以及括号匹配的应用
- Java堆栈的应用1----------堆栈的自定义实现以及括号匹配算法的Java实现
- 【数据结构】链表实现括号匹配
- 栈的顺序实现以及括号匹配判断程序
- KMP算法匹配原理以及C++实现
- 9.11 给定一个布尔表达式,由0、1、&、|、^等符号组成,以及一个想要的布尔结果result,实现一个函数,算出有几种括号的放法可使该表达式得出result的值。
- unity3d射线的原理用法以及一个利用射线实现简单拾取的小例子
- 红黑树原理解析以及Java实现
- mdev的使用方法和原理以及实现U盘或SD卡的自动挂载
- C++实现编译原理的词法分析器
- 【转载】MapReduce实现基本SQL操作的原理-join和group by,以及Dinstinct
- C指针原理(12)-编译原理-小型计算器实现
- HashMap和ArrayMap实现原理的区别以及各自优势
- Native App vs Web App 以及 Hybrid App的实现原理
- 凹凸贴图(Bump Map)实现原理以及与法线贴图(Normal Map)的区别
- 特征点匹配应用——图像拼接的原理与基于OpenCV的实现
- WebSocket实现长链接原理以及和ajax轮询、long poll的对比
- MVC数据验证原理及自定义ModelValidatorProvider实现无编译修改验证规则和错误信息