【数据结构】广义表的深度

int height(NODE* head){
    if(!head->link)return 0;//空表深度为0
    int ret=1;//
    NODE* p=head->link;
    while(p){//遍历链表的每一个结点,结点的最大深度加1即为链表的最大深度
        if(p->tag==1){//当结点是广义表时
            int h=height(p->dd.dlink)+1;//计算深度
            ret=h>ret?h:ret;//更新最大深度
        }
        p=p->link;
    }
    return ret;
}
//完整代码,供测试使用
#include<bits/stdc++.h>
using namespace std;
struct node
{
    int tag; // 当 tag==0时 第二个字段为 data 当 tag==1时 第二个字段为 dlink
    union
    {
    struct node * dlink;
    char data;
    } dd;
    struct node * link ;
};
typedef struct node NODE;
int height(NODE* head){
    if(!head->link)return 0;//空表深度为0
    int ret=1;//
    NODE* p=head->link;
    while(p){//遍历链表的每一个结点,结点的最大深度加1即为链表的最大深度
        if(p->tag==1){//当结点是广义表时
            int h=height(p->dd.dlink)+1;//计算深度
            ret=h>ret?h:ret;//更新最大深度
        }
        p=p->link;
    }
    return ret;
}
NODE* create(string s){//创建链表
    NODE* head=new NODE;
    NODE* p=head;
    p->tag=0;
    p->dd.data=-1;
    NODE* temp;
    for(int i=1;i<s.size()&&s[i]!=')';i++){
        if(s[i]==',')continue;
        if(isalpha(s[i])){
            temp=new NODE;
            temp->tag=0;
            temp->dd.data=s[i];
        }
        else if(s[i]=='('){
            temp=new NODE;
            temp->tag=1;
            temp->dd.dlink=create(s.substr(i));
            while(i<s.size()&&s[i]!=')')i++;
        }
        p->link=temp;
        p=p->link;
    }
    p->link=NULL;
    return head;
}
int main(){
    string s="()";
    cout<<"Create link."<<endl;
    NODE* head=create(s);
    cout<<"Height:"<<height(head);
}

简单改动代码,测试在递归表的情况下height函数的递归深度

//对height函数作改动
int height(NODE* head,int depth){//depth记录height函数的递归深度
    if(!head->link)return 0;//空表深度为0
    int ret=1;//
    NODE* p=head->link;
    while(p){//遍历链表的每一个结点,结点的最大深度加1即为链表的最大深度
        if(p->tag==1){//当结点是广义表时
            int h=height(p->dd.dlink,depth+1)+1;//计算深度
            ret=h>ret?h:ret;//更新最大深度
        }
        p=p->link;
    }
    return ret;
}


//对main函数作改动
int main(){
    string s="(a,b)";
    cout<<"Create link."<<endl;
    NODE* head=create(s);
    head->link->link->tag=1;
    head->link->link->dd.dlink=head;//符合题目中给的例子:C=(a,C);
    cout<<"Height:"<<height(head,0);
}

可以看到,递归深度达到26001,栈内存溢出,系统报错。实际上,递归表的深度是无穷大。

遍历广义表时,记录结点地址和经过次数,在遍历该结点的广义表时,如果某一结点经过了一次以上,则说明存在递归表。可用map实现。

bool is_recursive_link(NODE*head,map<NODE*,int>&nodecount){
    NODE* p=head;
    while(p){
        nodecount[p]++;
        if(nodecount[p]>1)return true;
        if(p->tag==1){
            return is_recursive_table(p->dd.dlink,nodecount);
        }
        p=p->link;
    }
    return false;
}
int main(){
    string s="(a,b)";
    cout<<"Create link."<<endl;
    NODE* head=create(s);
    head->link->link->tag=1;
    head->link->link->dd.dlink=head;
    map<NODE*,int>nodecount;
    if(is_recursive_link(head,nodecount))
        cout<<"This is a recursive link."<<endl;
    // cout<<"Height:"<<height(head,0);
}

在写递归程序时,要特别注意:

  • 警惕堆栈溢出

    如果递归求解的数据规模很大,调用层次很深,一直压入栈,会有堆栈溢出的风险

  • 设置中止条件

    如果没有中止条件,递归函数就会无休止地被调用

  • 减少重复运算

    可以通过储存中间计算结果减少递归函数的调用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值