栈的链表实现,以及编译原理中的括号匹配

一:

编译原理常有括号的匹配算法。用数组和链表实现的栈都可以实现。现用链表吧。

 

代码:

 

 

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来代替。
也可以看《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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值