您的位置:首页 > 其它

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

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐