ImageVerifierCode 换一换
格式:DOCX , 页数:20 ,大小:48.87KB ,
资源ID:12028346      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/12028346.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(广义表.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

广义表.docx

1、广义表5.4 广义表的类型定义ADT Glist 数据对象:Dei | i=1,2,.,n; n0; eiAtomSet 或 eiGList, AtomSet为某个数据对象 数据关系:LR| ei-1 ,ei D, 2in 广义表是递归定义的线性结构, LS = ( 1, 2, , n )其中:i 或为原子 或为广义表换句话说,广义表是一个多层次的线性结构。例如:D = (E, F)E = (a, (b, c)F = (d, (e)A = ( )B = (a, B) = (a, (a, (a, , ) ) )C = (A, D, F)广义表的结构特点:1) 广义表中的数据元素有相对次序;2)

2、广义表的长度定义为最外层包含的元素个数;3) 广义表的深度定义为所含括弧的重数;注意: “原子”的深度为“0”; “空表”的深度为14) 广义表可以共享;5) 广义表可以是一个递归的表;递归表的深度是无穷值,长度是有限值。6) 任何一个非空广义表 LS = ( 1, 2, , n) 均可分解为 表头 Head(LS) = 1 和 表尾 Tail(LS) = ( 2, , n) 两部分,可见,非空广义表的表头可以是原子,也可以是子表,而表尾必定是一个广义表。例如:LS = ( A, D )Head(LS) = A Tail(LS) = ( D )Head( D ) = E Tail( D ) =

3、 ( F )Head( E ) = a Tail( E ) = ( ( b, c) )Head( ( b, c) ) = ( b, c) Tail( ( b, c) ) = ( )Head( ( b, c) ) = b Tail( ( b, c) ) = ( c )Head( ( c ) ) = c Tail( ( c ) ) = ( ) 基本操作: 结构的创建和销毁 InitGList(&L); DestroyGList(&L); CreateGList(&L, S); CopyGList(&T, L); 状态函数 GListLength(L); GListDepth(L); GListEm

4、pty(L); GetHead(L); GetTail(L); 插入和删除操作 InsertFirst_GL(&L, e); DeleteFirst_GL(&L, &e); 遍历 Traverse_GL(L, Visit(); ADT GList5.5 广义表的表示方法 头、尾指针的链表结构表结点: tag=1 hp tp原子结点: tag=0 data构造存储结构的分析方法:1) 空表 ls= NIL 非空表 ls 1 若表头为原子 02) 空表 ls = NIL 非空表 ls 1 1 1 1 2 n 若子表为原子 05.6 递归函数的设计方法递归函数一个含直接或间接调用本函数语句的函数被称

5、之为递归函数,它必须满足以下两个条件:1) 在每一次调用自己时,必须是(在某种意义上)更接近于解;2) 必须有一个终止处理或计算的准则。例如:梵塔的递归函数void hanoi (int n, char x, char y, char z) if (n=1) move(x, 1, z); else hanoi(n-1, x, z, y); move(x, n, z); hanoi(n-1, y, x, z); 二叉树的遍历Status PreOrderTraverse( BiTree T, Status (Visit)(BiTree P) ) if (T) if (Visit(T-data)

6、if (PreOrderTraverse(T-lchild) if (PreOrderTraverse(T-rchild) return OK; return ERROR; else return OK; / PreOrderTraverse一、分治法(分割求解) (Divide and Conquer)对于一个输入规模为n的函数或问题,用某种方法把输入分割成k(1tag = ATOM) return 0; / 原子深度为0 for (max=0, pp=L; pp; pp=pp-ptr.tp) dep = GlistDepth(pp-ptr.hp); / 求以pp-ptr.hp为头指针的子表

7、深度 if (dep max) max = dep; return max + 1; / 非空表的深度是各子表的深度的最大值加1 / GlistDepth例二 复制广义表若 ls= NIL 则 newls = NIL否则 由 表头ls.hp 复制得 newhp 由 表尾 ls.tp 复制得 newtp 构造结点 newls, 并使 newls.hp = newhp, newls.tp = newtpStatus CopyGList(Glist &T, Glist L) / 采用头尾链表存储结构,由广义表L复制得到 / 广义表T。 if (!L) T = NULL; / 复制空表 else if

8、 (!(T = (Glist)malloc(sizeof(GLNode) exit(OVERFLOW); / 建表结点T-tag = L-tag;if (L-tag = ATOM) T-atom = L-atom; / 复制单原子else CopyGList(T-ptr.hp, L-ptr.hp); / 复制广义表T-ptr.hp的一个副本L-ptr.hp CopyGList(T-ptr.tp, L-ptr.tp); / 复制广义表T-ptr.tp的一个副本L-ptr.tp / else / else return OK; / CopyGList 例三 创建广义表的存储结构根据 LS = (1

9、, 2, , n ) 建广义表 ls若 LS = ( ) 则 ls = NIL否则 构造表结点 ls 分解出第一个子串1, 对应建广义表的表头 ls.hp 若剩余串非空,则构造表尾结点 ls.tp 分解出第二个子串2, 对应建广义表 依次类推,直至剩余串为空串止Status CreateGList(Glist &L, Sstring S) / 采用头尾链表存储结构,由广义表的书写形式串 / S创建广义表L。设emp=”()”。 if (StrCompare(S, emp) L = NULL; / 创建空表 else if (!(L = (Glist) malloc ( sizeof (GLNo

10、de) exit (OVERFLOW); / 建表结点 if (StrLength(S)=1) L-tag = ATOM; L-atom = S / 创建单原子广义表 else L-tag = LIST; p = L; SubString(sub, S, 2, StrLength(S)-2); /脱外层括号 do / 重复建n个子表sever(sub, hsub); /从sub中分离出表头串 hsubCreateGList(p-ptr.hp, hsub); q = p;if (!StrEmpty(sub) / 表尾不空 if (!(p = (GLNode *) malloc (sizeof(G

11、LNode) exit (OVERFLOW); p-tag = LIST; q-ptr.tp = p; while (!StrEmpty(sub); q-ptr.tp = NULL; / else / else return OK; / CreateGList 二、后置递归法 (Postponing the work)假如某个问题的的求解过程可以分成若干步进行,并且当前这一步的解可以直接求得,则先求出当前这一步的解,对于余下的问题,若问题的性质和原问题类似,则又可递归求解。显然,递归的终结状态应该是,当前的问题只需一步便可求得,对原问题而言,则是走到了求解的最后一步。例一 删除单链表中所有元素

12、为x的结点分析: 1) 单链表是一种顺序结构,必须从第一个结点起,逐个检查每个结点的数据元素;2) 从另一角度看,链表又是一个递归结构,若head是线性链表(a1, a2, , an)的头指针,则head.next是线性链表(a2, , an)的头指针。void Delete_LinearList(Link &L, Elem x) / 删除单链表中所有元素为x的结点 if (!L-next) fp = L-next;if (fp-data = x) L -next = fp-next; free(fp); Delete_LinearList(L,x);else Delete_LinearLis

13、t(fp, x); / Delete_LinearList例二 删除广义表中所有元素为x的原子结点分析:广义表和线性表比较:相似处:都是顺序结构不同处:广义表的数据元素可能还是个广义表void Delete_GL(Glist&L, AtomType x) /删除广义表中所有元素为x的原子结点 if (!L-ptr.tp) first = L-ptr.tp; head = first-ptr.hp;if (head-tag = Atom) & (head-atom = x) L-ptr.tp = first-ptr.tp; free(head); free(first); Delete_GL(L

14、,x);else if (head-tag = LIST) Delete_GL(head, x); Delete_GL(first, x); / Delete_GL例三 求n个数(的不同排列)可能构成的全部序列算法: 设序列的初始状态为空,之后从1至n逐个插入,插入的位置不同则构成不同的序列,对k, 则有k个插入位置。 一般情况下的问题提法为: 假设已知含1至k-1个元素的一个排列,则需要继续从k至n逐个插入,以构成n个元素的序列。这当前的一步是插入元素k, 它可有k个插入位置。例如,对于已经形成的序列:1,2, ,k-1,可以得到如下k个序列: k,1,2, ,k-1 1,k,2, ,k-1

15、 1,2,k, ,k-1 1,2, ,k-1,k则对于已经形成的(k-1)!个不同排列的序列,在插入k之后,得到k!个序列。下一步的问题就变成:已知含1至k个元素的一个排列,需要从k+1至n逐个插入,以构成n个元素的序列。若k=n, 则表明已求得全部解。逻辑结构采用线性表表示序列void Permute(List &L, int n, int k) / 已知线性表L中已含k-1个元素,本函数将 / 从k至n 的元素依次插入到表中不同位置, / 以求得n个元素的所有不同排列,并输出之 for ( i=1; i=k; +i) ListInsert( L, i, k); /元素k插入为第i个元素if

16、 (k=n) ListTraverse(L,Print); /遍历输出else Permute(L, n, k+1); /继续从k+1起插入ListDelete(L, i, e); /删除表中当前第i个元素 /Permute主函数: InitList(L); Permute(L, n, 1)以 n=3 为例,看图解的算法执行过程 算法执行前的初态 插入“1”之后的状态 1 2 1 1 23 2 1 2 3 1 2 1 3 3 1 2 1 3 2 1 上图树中每个结点表示线性表在程序执行过程中的一个状态(如:根结点表示算法执行前的状态;叶子结点表示插入“3”之后的状态),故称之为“状态空间树”或

17、“递归树”。其中,叶子结点表示“解”的状态,即“递归终结”的状态,所有非叶结点称为“活动结点”,表示求得部分解之后的状态,亦可称之为“可扩展的结点”,意为:算法所作是“扩展”非叶结点以求得问题的一种解。 算法Permute(L, n, k)的执行过程可以看成是先根遍历这棵状态空间树,访问结点的操作是“将第k个元素插入到第i棵子树根的第i个元素之前”,然后检查是否是叶子结点,若是,则输出,否则继续依次遍历各棵子树。 注意,这棵状态空间树在“遍历”过程中动态生成和销毁,访问结点的操作实际上是生成这棵树的根结点,而遍历结束返回时,删除这棵树。 因此,问题求解的核心是分析确定状态空间树的结构,即:从可

18、扩展的结点扩展出的子树的状态。在本算法的状态空间树中,第k层(遍历前的初态设为0层)的结点为插入第k个元素生成的子树根结点,因此可有k个。 类似问题很多,但对于某些问题,其状态空间树中的非叶结点不一定都是可扩展的结点,而是在求得问题的部分解之后,尚需进行检验,这类问题就是通常用“回朔法”求解的问题三、回溯法 回溯法是一种穷举方法。其基本思想为:假定一个问题的解能够表示成n元组(x1, x2, , xn )其中xi取值于集合Si,n元组的一个子组(x1,x2, ,xi ) in时,求得一个合法 / 布局,并输出之。 if (in) 输出棋盘的当前布局; / n为4时,即为4皇后问题 else f

19、or (j=1; jn) 输出一组解 (x1,x2, ,xn ); else while (!Empty(Si) 从Si中取得xi的一个值viSi;if (x1,x2, ,xi )满足约束条件) B(i+1)从Si中删除vi; /B 综合几点:1) 对于含有递归特性的问题,最好设计递归形式的算法。但也不要单纯追求形式,应在算法设计的分析过程中“就事论事”。例如,在利用分割求解设计算法时,子问题和原问题的性质相同;或者,问题的当前一步解决之后,余下的问题和原问题性质相同,则自然导致递归求解。2) 实现递归函数,目前必须利用“栈”。一个递归函数必定能改写为利用栈实现的非递归函数;反之,一个用栈实现

20、的非递归函数可以改写为递归函数。需要注意的是递归函数递归层次的深度决定所需存储量的大小。3) 分析递归算法的工具是递归树,从递归树上可以得到递归函数的各种相关信息。例如:递归树的深度即为递归函数的递归深度;递归树上的结点数目恰为函数中的主要操作重复进行的次数;若递归树蜕化为单支树或者递归树中含有很多相同的结点,则表明该递归函数不适用。4) 递归函数中的尾递归容易消除。例如:先序遍历二叉树可以改写为:Status PreOrderTraverse( BiTree T, Status (Visit)(BiTree P) ) While (T) if (Visit(T-data) if (PreOrderTraverse(T-lchild) T = T-rchild; else return ERROR; return OK; / PreOrderTraverse5) 可以用递归方程来表述递归函数的时间性能。例如:假设解n个圆盘的梵塔的执行时间为T(n)则递归方程为 T(n) = 2T(n-1) + C, T(0) = 0

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1