zoukankan      html  css  js  c++  java
  • 函数:广搜定义与深搜实现

    本篇谈及以下内容:

    1.函数调用树与代码跳转,调用展开成递归

    2.深搜与广搜的优劣,栈与队列的选择

    3.静态链与动态链

    4.异常的处理

    5.内存管理:栈与堆的设计语义

    6.泛化栈与堆的设计

    1.函数调用树

    函数的全部调用组成一棵调用树

    每个叶节点代表调用的终结条件,或自身不含调用的函数,

    父节点到子节点表示调用方进入被调用方

    子节点到父节点表示调用完成的回溯

    每个节点都需要有回溯动作(返回地址)

    当我们定义一个函数时,通常是以广搜树的角度考虑的:

    即:当前定义的函数顺序执行许多步骤,并且假定各个步骤保证其功能完成,而不是一直深究到最内嵌套函数的执行。

    然而,程序执行时的顺序是按深搜树的遇到调用则展开,(保存返回地址)调用完成则回溯

    所有递归都可以展开成迭代:

    每次迭代的语义:

    判断回溯或是调用

    1.父——子:调用,得到被调方的代码地址,跳转

    2.子——父:回溯,完成计算,取出保存的返回地址,跳转

    无论是调用动作还是回溯动作,都是根据地址跳转。可见将递归展开实际上完成的是一次树的深搜遍历。

    2.深搜与广搜的优劣,栈与队列的选择

    深搜用栈实现,广搜用队列实现

    栈的长度最长为调用深度(树高)这是栈实现调用的空间高效性的保证。

    队列的长度最长为某个深度的节点总数(更精确的,是相邻两层的组合情况)

    但是!上述还没有讨论需要回溯的情况。

    当需要回溯时,队列需要维护整棵树,或者说,单个队列已经无法维护函数调用的语义了。

    调用——回溯这两个动作与栈的入出完美的一致。

    3.静态链与动态链

    上文中没有区分开一个细节:一棵树是一次具体调用的实例,不同的调用产生的树不同。

    每个节点都需要记录向上回溯的指针(指向父),这个指针的语义:

    被调用方的返回地址=调用者的某个代码行

    称为帧指针

    要是一个函数还没结束,则都保留着帧指针

    栈空间上保留着一条调用路径,栈1返回地址——栈2的帧(指向后序代码)——移动到栈2的结束——栈2的返回地址

    这样构成的链就叫动态链(调用序列不可静态预测)

    在树上表现为回溯边

    静态链就比较简单了,取决于调用与被调的代码块嵌套关系(定义处与调用处不同)

    在树上表现为一条路径上,重复出现的同函数名节点,下方的指向第一次出现位置(回向边)

    静态链与动态链语义上截然不同(一个用于返回,一个用于查找外层变量)

    在实现上有共同点,都是保留指针用于回溯:对于调用回溯,一个函数可能被各种函数调用;对于查找外层变量,外层函数可能被内层调用(做间接引用回到定义位置)

    4.异常的处理

    可能异常代码块,平行于处理异常代码块。这是个词法上(静态)的if not-else结构

    但异常是在执行的过程中出现的,调用方会不会对错误有个更高抽象层次的分析?调用A失败了,推测导致异常的输入有可能存在某种规律(先验)

    根据调用的顺序回溯(不同于动态链,中间穿插着处理函数)

    所以异常是一种动态静态思想都有的设计

    5.内存管理:栈与堆的设计语义

    栈划分出一块空间(栈空间),具体由两两相邻的栈指针划分开

    而回溯的访问机制甚至不需要知道所有的划分,而是只需要最后一次划分(保存,恢复栈指针)

    如果用到的所有对象大小(形参+局部)大小确定,可以快速的划分与计算地址(偏移)

    否则:

    1.可变对象转化为:地址(大小一致)+内情向量(分配到堆上?)

    2.两次划分,第一次划分出固定大小,第二次划分出可变大小

    大小静态可知用于对齐?

    堆:语义:生存周期跨作用域

    垃圾回收:1.假定最后一个链接为硬链接。2.无可访问入口

    6.泛化栈与堆的设计

  • 相关阅读:
    how to uninstall devkit
    asp.net中bin目录下的 dll.refresh文件
    查找2个分支的共同父节点
    Three ways to do WCF instance management
    WCF Concurrency (Single, Multiple, and Reentrant) and Throttling
    检查string是否为double
    How to hide TabPage from TabControl
    获取当前系统中的时区
    git svn cygwin_exception
    lodoop打印控制具体解释
  • 原文地址:https://www.cnblogs.com/qmcj/p/9253404.html
Copyright © 2011-2022 走看看