建立广义表的算法

需要在了解广义表这种数据结构的基础上才能读懂本文。也就是说,如果能看懂我的上一篇博客,应该就能看懂这篇博客。http://blog.csdn.net/sinat_34927324/article/details/53932226(上篇博客的链接)

书上的算法实在是难懂,去翻看别人博客上的算法,好像比我的教科书上的要简单一些,但是好像没有处理子表是共享表的功能。于是我用了两个晚上才看懂书上的算法,在这个跨年夜拿出来跟大家分享一下。哈哈


假设一个广义表的元素类型是字符型,每一个元素是英文字母,并假定广义表从输入流对象istream输入。输入形式如:

"D( B(a,b), C( u, (x,y,z) ), A(#) );"

输入流建立起来的广义表如下图所示。



我们可以看到输入的字符串里面有大写英文字母(代表子表结点),小写英文字母(代表原子结点),左右括号,逗号,#号还有分号。

在算法的执行过程中,对于输入流对象输入的一个字符,检测它的内容。如果遇到用大写英文字母表示的表名,首先检查这个表名是否存在,如果是,说明该表是共享表,只要将附加头结点的引用计数加一即可;如果不是,保存该表名并建立相应广义表。表名后面一定是左括号‘(’,如果不是,说明输入错误,是则建立广义表结构。如果遇到小写字母表示的原子,则建立原子元素结点;如果遇到右括号‘)’,子表链收尾并退出递归。

我们的任务就是设计一个算法,根据输入字符串来建立如图所示的广义表。

"D( B(a,b), C( u, (x,y,z) ), A(#) );"

    我们从左到右输入这个字符串,第一个输入的是D,常理来说此时我们应该建立广义表D的一个附加头结点,但是为了把大写字母统一操作。

(1)我们此时建立一个子表结点。(=0附加头结点;=1原子结点;=2子表结点)


(2)然后我们知道之后扫描到的左括号是没有作用的,因此我们应该在此处再输入一个字符使程序跳过左括号。

(3)建立完子表结点后我们需要先建立这个子表,然后再建立后继表(这两处都是递归)。因此我们首先要建立子表的附加头结点。


建立完附加头结点之后我们要建立ls的子表Createlist(ls->info.hlink->tlink)参数指针简称ls1,在这一层递归中我们输入的字符轮到了B,因此我们重复进行上面三步的操作:


同理我们又递归调用Createlist(ls1->info.hlink->tlink):参数指针简称ls2  建立ls1的子表,这一层递归中我们输入的字符是a,因此我们需要建立一个原子结点。


建立完原子结点后我们继续递归调用建立它的该子表的后继表Createlist(ls2),至于此处为什么是ls2不是ls2->tlink,是因为在这一层递归中我们将要输入的字符串是逗号“,”,因此我们需要跳过这个逗号,在判断输入字符为逗号后我们才调用Createlist(ls2->tlink)指针简称ls3来继续建立后继表。

      跳过了逗号后,在这一层递归中我们输入的字符是b,因此我们再次建立原子结点


又递归调用Createlist(ls3),这一层递归中我们输入的字符是右括号,表示子表建立完毕。此时我们另ls,3->tlink=NULL,表示ls1的子表被建立完毕。递归返回到ls1的递归空间接着建立它的后继表Createlist(ls1),至于此处参数为什么不是ls1->tlink,如上所述因为下一个符号是逗号。

  后面同理递推就可以根据输入流建立起这个广义表啦。

  现在大家再看这段代码,思路是否更清晰一点了呢?

void Createlist(istream& istr,GenListNode *&ls){
	char chr;
	istr>>chr;
	if(isalpha(chr)&&isupper(chr)||chr=='('){
		ls=new GenListNode;
		ls->utype=2;
                istr>>chr;
		if(chr!='(')
		exit(1);		
		ls->info.hlink=new GenListNode;
		ls->info.hlink->utype=0;
		ls->info.hlink->info.ref=1;
		Createlist(istr,ls->info.hlink->tlink,L1,L2);
		Createlist(istr,ls,L1,L2);
	}
	else if(isalpha(chr)&&islower(chr)){
		ls=new GenListNode;
		ls->utype=1;
		ls->info.value=chr;
		Createlist(istr,ls,L1,L2);
	}
	else if(chr==',')
		Createlist(istr,ls->tlink,L1,L2);
	else if(chr==')')
		ls->tlink=NULL;
	else if(chr=='#')
		ls=NULL;
}

细心的朋友不难发现这段代码建立起来的广义表还有一点问题,就是多了一个子表结点,只要再通过另一个函数把该子表结点删掉,然后把头指针指向正确的位置就可以了。

如果建立的表中含有共享表,我们只要把代码稍作改动就可以了

void Createlist(istream& istr,GenListNode *&ls,SeqList<char>& L1,SeqList<GenListNode*>& L2){
	char chr;
	istr>>chr;
	if(isalpha(chr)&&isupper(chr)||chr=='('){
		ls=new GenListNode;
		ls->utype=2;
		if(isalpha(chr)&&isupper(chr)){
			int m=L1.Search(chr);
			int n=L1.Length();
			if(m!=0){
				GenListNode *p=NULL;
				L2.getData(m,p);
				p->info.hlink->info.ref++;
			}
			else{
				L1.Inseart(n,chr);
				L2.Inseart(n,ls);
			}
			istr>>chr;
			if(chr!='(')
				exit(1);
		}
		ls->info.hlink=new GenListNode;
		ls->info.hlink->utype=0;
		ls->info.hlink->info.ref=1;
		Createlist(istr,ls->info.hlink->tlink,L1,L2);
		Createlist(istr,ls,L1,L2);
	}
	else if(isalpha(chr)&&islower(chr)){
		ls=new GenListNode;
		ls->utype=1;
		ls->info.value=chr;
		Createlist(istr,ls,L1,L2);
	}
	else if(chr==',')
		Createlist(istr,ls->tlink,L1,L2);
	else if(chr==')')
		ls->tlink=NULL;
	else if(chr=='#')
		ls=NULL;
}



 


      

        

     






  • 6
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值