数据结构5.5_广义表的递归算法

对一些可以用递归算法解决的问题,通常可以先写出问题求解的递归定义

和第二数学归纳类似,递归定义由基本项归纳项两部分组成。

 

递归定义的基本项描述了一个或几个递归过程的终结状态。虽然一个有限的递归可以描述一个无限的计算过程。

但任何实际应用的递归过程,除错误情况外,必定能经过有限层次的递归而终止。

所谓的终结状态,指的是不需要继续递归而可直接求解的状态。

 

递归定义的归纳项描述了如何实现从当前状态到终结状态的转化。

递归设计的实质是:当一个复杂问题可以分解成若干个子问题来处理时,

其中某些子问题与原问题由相同的特征属性。则可以利用与原问题相同的分析处理方法。

反之,这些问题解决了,原问题也就迎刃而解了。

递归定义的归纳项描述的是原问题与子问题的转化关系

 

递归函数的设计用的是归纳思维的方法,在设计递归函数时,应注意:

严格定义函数的功能和接口;

切忌想得太深太远;

用归纳假设进行归纳证明时,决不能怀疑归纳假设是否正确;

 

下面讨论广义表的3种操作

首先约定所讨论的广义表都是非递归表且无共享子表;

 

求广义表的深度

广义表的深度指的是广义表种括弧的重数;

空表的深度为1,因为有一对括弧;

原子的深度为0;

解题思路

1)遍历该广义表各个数据元素,求该元素的深度。如果该元素是原子,则返回深度0;如果该元素是子表,则遍历该子表的深度;

2)递归的出口状态,或者叫做终结状态:当遍历数据元素为原子时返回0,当遍历数据元素为空表时,返回1;

3)设置一个变量max用来记录数据元素中最长的深度;初始化max=0;遍历过程中max与返回的整型值进行比较,取值较大的那一个。直到程序结束。max+1就是广义表的深度;

代码实现

1 int GetGListDepth(GList L){
2     if(!L) return 1;
3     if(L->tag==0) return 0;
4     for(int max=0, pp=L;pp;pp=pp->ptr.tp){
5         dep=GetGListDepth(pp->ptr.hp);
6         if(dep>max)  max=dep;
7     }    
8     return max+1  //非空表的深度是各元素深度最大值加1
9 }

 

 

复制广义表

 任何一个非空的广义表均可分解成表头和表尾。反之,一对确定的表头和表尾可唯一确定一个广义表。

由此,复制一个广义表只要分别复制其表头和表尾,然后合成即可。

复制一个广义表,也是不断的复制表头和表尾的过程。如果表头或者表尾同样是一个广义表,依旧复制其表头和表尾。

所以,复制广义表的过程,其实就是不断的递归,复制广义表中表头和表尾的过程。

 

递归的出口条件:

  如果当前遍历的数据元素为空表,则直接返回空表。

  如果当前遍历的数据元素为该表的一个原子,那么直接复制,返回即可。

 

代码实现:

 1 Status CopyGList(GList &T, GList L){
 2         if(!L) T=NULL;  //直接返回空表
 3         else{
 4                 if(!(T=(GList)malloc(sizeof(GLNode))))  exit(OVERFLOW);  //如果L不是空表,给T分配内存空间
 5                 T->tag=L->tag;
 6                 if(L->tag ==ATOM)  T->atom=L->atom; //直接复制原子
 7                 else
 8                 {
 9                         CopyGList(T->ptr.hp, L->ptr.hp); //复制表头
10                         CopyGList(T->ptr.tp, L->ptr.tp); //复制表尾
11                 }
12        }
return OK;
13 }

 

建立广义表的存储结构

 

 

相关链接:

数据结构29:广义表的长度和深度:https://www.cnblogs.com/ciyeer/p/9040533.html 

数据结构30:广义表的复制:https://www.cnblogs.com/ciyeer/p/9040553.html

转载于:https://www.cnblogs.com/grooovvve/p/10398313.html

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
广义可以看作是一个树状结构,其中每个节点可能是一个原子元素或者是一个子广义。对于一个广义,它可以被示为一个由左括号、右括号和逗号组成的字符串。例如,广义 (1,2,(3,4)) 可以示为字符串 "(1,2,(3,4))"。 下面是使用算法创建广义的C语言实现: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct node { char data; struct node *next; struct node *sublist; } Node; // 创建子 Node *create_sublist(char *str, int *index) { Node *cur = NULL; Node *head = NULL; while (str[*index] != ')' && str[*index] != '\0') { if (str[*index] == '(') { // 归创建子 (*index)++; Node *sublist = create_sublist(str, index); if (cur) { cur->next = NULL; cur->sublist = sublist; } else { head = sublist; } cur = sublist; } else if (str[*index] == ',') { // 创建新节点 (*index)++; Node *node = (Node *) malloc(sizeof(Node)); node->data = '\0'; node->next = NULL; node->sublist = NULL; if (cur) { cur->next = node; } else { head = node; } cur = node; } else { // 创建新节点 Node *node = (Node *) malloc(sizeof(Node)); node->data = str[*index]; node->next = NULL; node->sublist = NULL; if (cur) { cur->next = node; } else { head = node; } cur = node; (*index)++; } } (*index)++; return head; } // 创建广义 Node *create_generalized_list(char *str) { int index = 0; if (str[index] == '(') { index++; return create_sublist(str, &index); } else { return NULL; } } // 打印广义 void print_generalized_list(Node *head) { printf("("); while (head) { if (head->sublist) { // 打印子 print_generalized_list(head->sublist); head = head->next; } else if (head->data == '\0') { // 打印分隔符 printf(","); head = head->next; } else { // 打印原子元素 printf("%c", head->data); head = head->next; } } printf(")"); } int main() { char *str = "(1,2,(3,4))"; Node *head = create_generalized_list(str); print_generalized_list(head); return 0; } ``` 在这个实现中,我们使用了一个结构体 `Node` 来广义中的节点。其中,`data` 字段示节点的数据,`next` 字段示指向下一个节点的指针,`sublist` 字段示指向子的指针。在创建广义时,我们首先判断当前字符是左括号、右括号还是逗号,然后根据不同的情况进行处理。如果当前字符是左括号,那么我们归调用 `create_sublist` 函数来创建子;如果当前字符是逗号,那么我们创建一个新节点作为分隔符;如果当前字符是原子元素,那么我们创建一个新节点来存储它。在创建完成节点后,我们将它添加到广义中,并且更新指向最后一个节点的指针 `cur`。最后,我们返回广义的头结点 `head`。 在程序的主函数中,我们先定义了一个字符串 `str` 来广义的字符串示。然后,我们调用 `create_generalized_list` 函数来创建广义,并且调用 `print_generalized_list` 函数来打印广义。在打印广义时,我们首先打印左括号,然后遍历广义中的所有节点。对于每个节点,如果它是一个子,那么我们归调用 `print_generalized_list` 函数来打印它;如果它是一个分隔符,那么我们打印逗号;如果它是一个原子元素,那么我们打印它。最后,我们打印右括号来结束广义的打印。 注意:在实际编写代码时,我们应该为 `Node` 结构体添加一些边界检查代码,以避免访问非法内存。此外,我们也应该在程序运行结束后释放动态分配的内存。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值