【问题标题】:"Executing" a body of statements without recursion不递归地“执行”语句体
【发布时间】:2013-04-25 18:59:39
【问题描述】:

我试图通过在我的旧家庭作业上对范围 { } 内语句体的简化执行建模来掌握迭代和递归之间的关系。假设我有两种语句类型:while 语句和赋值语句。

现在,我假设 while 语句的条件始终为真。 编辑:另外,假设 while 语句只执行一次(即我应该称它为 if 语句)

在递归中,这很简单:

executeBody( body )
{
  for each stmt in body
  {
    switch (stmt)
    {
      case ASSIGNMENT:
       // work
       break;

      case WHILE-STMT:
        executeBody(whileStmt->body)
        break;
    }
  }
}

但是,我在迭代时遇到了麻烦。我知道我需要模拟一个堆栈,但我只是无法概念化如何在执行下一条语句之前执行 while 语句中的所有语句。这是我所拥有的模型:

executeBody( body )
{
  for each stmt in body
  {
    case ASSIGNMENT:
      // work
      break;

    case WHILE-STMT:
    {
       stack< body > stack;
       stack.push(whileStmt->body);     
       while (stack isNotEmpty)
       {
          for each stmt (in each body) in stack
          {
            case ASSIGNMENT:
              // work;
              break;

            case WHILE-STMT:
              //stack.push(this_whileStmt->body);
              // ????
              break;
          }
       }
    }  
  }
}

编辑:更改了递归示例以显示主体是一系列语句。

【问题讨论】:

  • 是您发布正确代码的迭代伪代码还是您自己的代码
  • 这是我自己的代码 - 这是不正确的,因为它还没有完成
  • 我会以while(cond) cmd 开头,其中 cmd 可以是语句或块。然后你维护一堆 cmd / cond / exec 状态元组。当你打了一会儿,如果条件,推三倍。标准块推动虚假条件。外循环是将栈顶的exec状态推进,获取cmd,handle。如果最上面已经完成,请检查 cond 并弹出或重置 exec 状态。
  • 主体是一系列语句。我已经修改了递归示例,添加了一个 for each 和 switch 语句
  • “在递归中,这很简单”或者可能不是。每个 while 语句的主体只执行一次,这并不完全正确。

标签: c++ loops recursion


【解决方案1】:

首先,我会放弃你的外循环。这是多余的。

   stack< body > stack;
   stack.push(body);     
   while (stack isNotEmpty)
   {
      for each stmt (in stack.pop()) // pop the top statement off of your stack
      {
        case ASSIGNMENT:
          // work;
          stmt.Remove()
          /*you don't need to break here.  just go onto the next operation*/

        case WHILE-STMT:
          stack.push(stmt->body);
          stmt.Remove()
          stack.push(stmt); 
          break;
      }

一旦您遇到WHILE-STMT: 情况,代码将中断并继续处理堆栈的顶部项目,即您刚刚放入其中的代码块。

一旦该块执行完毕,它将从堆栈中弹出(您在for 声明中执行此操作),并且它将继续执行您当前的块。清除当前语句并将工作块推回堆栈的全部目的是为了能够像这样恢复。

【讨论】:

  • 我看不出循环执行后如何正确恢复。 stmt.Remove() 是做什么的?
  • @phant0m 除了将while statements 视为普通code blocks(与OP 递归示例完全一样)您认为它恢复时会发生什么?
  • @phant0m 它应该从块中删除语句。
  • 视实际实现而定,如果不喜欢移除,可以标记为已执行,或者保留索引。
  • 我明白了,这是有道理的:+1
【解决方案2】:

您将堆栈放在错误的位置。它应该在 executeBody 例程的顶部声明。看看这个:

executeBody(body) {
    stack<body> work;

    stack.push(body);

    while (stack isNotEmpty) {
        item = stack.pop();
        switch (item) {
            case ASSIGNMENT:
                // work;
                break;
            case WHILE-STMT:
                stack.push(item);
                break;
        }
    }
}

这个伪代码应该清楚地表明你所有的身体都在堆栈上。其中一些做分配,一些做同时。

【讨论】:

  • 在WHILE_STMT中应该读取stack.push(item->body),否则会变成死循环。
  • 一个小改动:您将需要一个循环来迭代地将 while-stmt 项推送到堆栈..
  • 原始的第二个代码片段表明body 是一个语句序列。您的代码没有对其进行任何类型的迭代,有些东西已经关闭。
  • 感谢 cmets - 我只是想说明堆栈应该用于整个例程的概念,而不仅仅是在 case 语句中。我并没有试图钻得很深。 (但我确实理解这里的观点。)
猜你喜欢
  • 2014-06-25
  • 2012-08-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-20
  • 1970-01-01
  • 2015-12-22
  • 1970-01-01
  • 2015-05-15
相关资源
最近更新 更多