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.泛化栈与堆的设计

  • 相关阅读:
    [ 打败 IE 的葵花宝典 ] IE6中css常见BUG全集及解决方案
    js获取URl传递的参数
    几种C#框架提供的数据结构对单值查找的效率比较
    C#Hashtable与Dictionary性能
    Sql server 使用存储过程分页显示
    arrayList使用 与 foreach 使用
    LeetCode 047. 全排列 II DFS
    LeetCode 046. 全排列 dfs 和 dfs_swap
    LeetCode 048. 旋转图像
    LeetCode 040. 组合总和 II 非SET去重
  • 原文地址:https://www.cnblogs.com/qmcj/p/9253404.html
Copyright © 2011-2022 走看看