C泛型:如何实现BST键范围函数?

时间:2018-01-13 22:10:20

标签: c pointers generics binary-search-tree valgrind

我想在C中实现两个在BST上运行的通用函数,并将其节点的键存储在一个返回给调用者的单链表中。一个函数存储BST的所有密钥,另一个函数仅存储给定范围内的密钥。这两个函数都执行“按顺序”访问,这意味着密钥以升序存储,并在列表中插入尾部。

由于我没有发现任何伪代码,我试图找到一种方法来实现这一点,但目前它不起作用,Valgrind警告我几个问题,如“条件跳转或移动取决于未初始化的价值“。 我试图将列表从一个函数转移到另一个函数或者一些错误的malloc()或free()的方式可能有问题。

我还有一个关于如何改进整个代码的问题:不是使用两个非常相似但最终做不同事情的不同函数,根据输入使用只做一个不同的事情可能会很棒它收到了。必须存储的键范围包括“low_key”和“high_key”,以便两者之间的所有键都有效。 由于这两个键是void的指针,如果它们都被传递为NULL,则可能意味着我想存储BST的所有键。这是正确的还是会导致意想不到的结果?

  • list_t是指向列表节点的指针(指向node_t);
  • node_t是列表的一个节点,它指向一个关键字段;
  • bst_t是指向主BST结构的指针,该结构指向根节点(bst_node_t);
  • bst_node_t是BST的节点;
  • comparator_t是指向比较通用数据的函数的指针,存储在主BST结构中;如果第一个元素> 1,则返回1第二个元素,否则为-1,如果它们相等则为0;
  • low_key是键范围的下限,high_key是上限。

存储所有密钥的代码

list_t bst_keys_all(const bst_t tree) 
{
    if (bst_is_empty(tree))
        return NULL;

    // pointer to head
    list_t list = malloc(sizeof(node_t));

    if (list == NULL)
        return NULL;

    // head passed as pointer to pointer to emulate pass by reference
    traverse1(tree->root, &list);
    return list;  
}

void traverse1(node_t *node, list_t *list)
{
    if (node == NULL)
        return;

    traverse1(node->left, list);
    append(node, list);
    traverse1(node->right, list);
}

void append(bst_node_t *tree_node, list_t *head)
{
    list_t new_node = malloc(sizeof(node_t));
    list_t last_node = *head;

    new_node->key = tree_node->key;
    new_node->next = NULL;

    if (*head == NULL) {
        *head = new_node;
        return;
    }

    while (last_node != NULL) {
        last_node = last_node->next;
    }

    last_node->next = new_node;
    free(new_node);
    return;
}

仅在一个范围内存储密钥的代码

list_t bst_keys_range(const bst_t tree, const void *low_key, const void *high_key)
{
    if (bst_is_empty(tree))
        return NULL;

    list_t list = malloc(sizeof(node_t));

    if (list == NULL)
        return NULL;

    // head of the list passed as pointer to pointer again
    // key_cmp is a field of the main bst structure that points to a comparator_t function
    traverse2(tree->root, &list, low_key, high_key, tree->key_cmp);
    return list;
}

void traverse2(node_t *node, list_t *list, const void *low_key, const void *high_key, comparator_t cmp)
{
    if (node == NULL)
        return;

    if (cmp(low_key, node->key) < 0) 
        traverse2(node->left, list, low_key, high_key, cmp);

    if (cmp(low_key, node->key) <= 0 && cmp(high_key, node->key) >= 0) 
        append(node, list); // it's the same function used in the code above

    if (cmp(high_key, node->key) > 0) 
        traverse2(node->right, list, low_key, high_key, cmp);
}

0 个答案:

没有答案