栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

如何实现具有延迟传播的段树?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

如何实现具有延迟传播的段树?

惰性传播几乎总是包含某种哨兵机制。您必须验证不需要传播当前节点,并且此检查应该简单快捷。因此,有两种可能性:

  1. 牺牲一点内存以在您的节点中保存一个字段,可以很容易地检查它
  2. 牺牲一点运行时间,以检查节点是否已传播以及是否必须创建其子节点。

我坚持自己的第一个。检查分段树中的节点是否应具有子节点非常简单(

node->lower_value !=node->upper_value
),但是您还必须检查这些子节点是否已经构建(
node->left_child,node->right_child
),因此我引入了传播标记
node->propagated

typedef struct lazy_segment_node{  int lower_value;  int upper_value;  struct lazy_segment_node * left_child;  struct lazy_segment_node * right_child;  unsigned char propagated;} lazy_segment_node;

初始化

要初始化我们称之为节点

initialize
的指针的节点指针(或
NULL
)和期望
upper_value
/
lower_value

lazy_segment_node * initialize(    lazy_segment_node ** mem,     int lower_value,     int upper_value){  lazy_segment_node * tmp = NULL;  if(mem != NULL)    tmp = *mem;  if(tmp == NULL)    tmp = malloc(sizeof(lazy_segment_node));  if(tmp == NULL)    return NULL;  tmp->lower_value = lower_value;  tmp->upper_value = upper_value;  tmp->propagated = 0;  tmp->left_child = NULL;  tmp->right_child = NULL;  if(mem != NULL)    *mem = tmp;  return tmp;}

访问

到目前为止,还没有什么特别的事情。这看起来像其他所有通用节点创建方法。但是,为了创建实际的子节点并设置传播标志,我们可以使用一个函数,该函数将在同一节点上返回一个指针,但是在需要时传播它:

lazy_segment_node * accessErr(lazy_segment_node* node, int * error){  if(node == NULL){    if(error != NULL)      *error = 1;    return NULL;  }    if(node->propagated)    return node;          if(node->upper_value == node->lower_value){    node->propagated = 1;    return node;  }    return node;}

如您所见,传播的节点几乎会立即退出该功能。相反,未传播的节点将首先检查它是否实际上应包含子节点,然后在需要时创建它们。

这实际上是惰性评估。直到需要时才创建子节点。注意,

accessErr
它还提供了一个附加的错误接口。如果您不需要它,请
access
改用:

lazy_segment_node * access(lazy_segment_node* node){  return accessErr(node,NULL);}

自由

为了释放这些元素,您可以使用通用节点释放算法:

void free_lazy_segment_tree(lazy_segment_node * root){  if(root == NULL)    return;  free_lazy_segment_tree(root->left_child);  free_lazy_segment_tree(root->right_child);  free(root);}

完整的例子

下面的示例将使用上述函数基于间隔[1,10]创建延迟评估的分段树。您可以看到,第一次初始化后

test
没有子节点。通过使用,
access
您实际上生成了那些子节点并可以获取它们的值(如果这些子节点通过分段树的逻辑存在):

#include <stdlib.h>#include <stdio.h>typedef struct lazy_segment_node{  int lower_value;  int upper_value;  unsigned char propagated;  struct lazy_segment_node * left_child;  struct lazy_segment_node * right_child;} lazy_segment_node;lazy_segment_node * initialize(lazy_segment_node ** mem, int lower_value, int upper_value){  lazy_segment_node * tmp = NULL;  if(mem != NULL)    tmp = *mem;  if(tmp == NULL)    tmp = malloc(sizeof(lazy_segment_node));  if(tmp == NULL)    return NULL;  tmp->lower_value = lower_value;  tmp->upper_value = upper_value;  tmp->propagated = 0;  tmp->left_child = NULL;  tmp->right_child = NULL;  if(mem != NULL)    *mem = tmp;  return tmp;}lazy_segment_node * accessErr(lazy_segment_node* node, int * error){  if(node == NULL){    if(error != NULL)      *error = 1;    return NULL;  }  if(node->propagated)    return node;  if(node->upper_value == node->lower_value){    node->propagated = 1;    return node;  }  node->left_child = initialize(NULL,node->lower_value,(node->lower_value + node->upper_value)/2);  if(node->left_child == NULL){    if(error != NULL)      *error = 2;    return NULL;  }  node->right_child = initialize(NULL,(node->lower_value + node->upper_value)/2 + 1,node->upper_value);  if(node->right_child == NULL){    free(node->left_child);    if(error != NULL)      *error = 3;    return NULL;  }    node->propagated = 1;  return node;}lazy_segment_node * access(lazy_segment_node* node){  return accessErr(node,NULL);}void free_lazy_segment_tree(lazy_segment_node * root){  if(root == NULL)    return;  free_lazy_segment_tree(root->left_child);  free_lazy_segment_tree(root->right_child);  free(root);}int main(){  lazy_segment_node * test = NULL;  initialize(&test,1,10);  printf("Lazy evaluation testn");  printf("test->lower_value: %in",test->lower_value);  printf("test->upper_value: %in",test->upper_value);  printf("nNode not propagatedn");  printf("test->left_child: %pn",test->left_child);  printf("test->right_child: %pn",test->right_child);  printf("nNode propagated with access:n");  printf("access(test)->left_child: %pn",access(test)->left_child);  printf("access(test)->right_child: %pn",access(test)->right_child);  printf("nNode propagated with access, but subchilds are not:n");  printf("access(test)->left_child->left_child: %pn",access(test)->left_child->left_child);  printf("access(test)->left_child->right_child: %pn",access(test)->left_child->right_child);  printf("nCan use access on subchilds:n");  printf("access(test->left_child)->left_child: %pn",access(test->left_child)->left_child);  printf("access(test->left_child)->right_child: %pn",access(test->left_child)->right_child);  printf("nIt's possible to chain:n");  printf("access(access(access(test)->right_child)->right_child)->lower_value: %in",access(access(access(test)->right_child)->right_child)->lower_value);  printf("access(access(access(test)->right_child)->right_child)->upper_value: %in",access(access(access(test)->right_child)->right_child)->upper_value);  free_lazy_segment_tree(test);  return 0;}

结果(ideone)

惰性评估测试test-> lower_value:1test-> upper_value:10节点未传播test-> left_child :(无)test-> right_child :(无)通过访问传播的节点:访问(测试)-> left_child:0x948e020访问(测试)-> right_child:0x948e038节点随访问而传播,但子节点不是:访问(测试)-> left_child-> left_child:(无)访问(测试)-> left_child-> right_child :(无)可以对子孩子使用访问权限:访问(test-> left_child)-> left_child:0x948e050访问(test-> left_child)-> right_child:0x948e068可以链接:access(访问(access(test)-> right_child)-> right_child)->下限值:9access(访问(访问(测试)-> right_child)-> right_child)->上限值:10


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/617011.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号