2D алгоритм бинарного дерева

1

Фон:

Я пытаюсь воспроизвести этот Алгоритм в C, Packing Blocks into a Fixed Rectangle и я уже задаю вопрос об этом, но все еще не получаю те же результаты. Я нашел конкретный ввод, который вызывает "ошибку", и, чтобы показать, что я статически устанавливаю значения в коде, чтобы облегчить его тестирование.

Мой код C:

#include <stdio.h>
#include <stdlib.h>
#define COUNT 10

typedef struct Block
{
    struct Node* fit;
    int width;
    int height;
    int x;
    int y;
    int id;

} Block;

typedef struct Node 
{
    struct Node* parent;
    struct Node* down;
    struct Node* right;
    int used;   
    int width;
    int height;
    int x;
    int y;

} Node;

Node *findNode(Node *root, int w, int h);
Node *splitNode(Node **node, int w, int h);
void print2D(Node *root, int space);
int MAX(int a, int b);
int MIN(int a, int b);


int main()
{
    Node *root;
    Block **blocks;
    int boardWidth, boardHeight, totalBlocks;
    int i, j;


    boardWidth = 500;
    boardHeight = 500;

    root = malloc(sizeof(Node));
    root->x = 0;
    root->y = 0;
    root->width = boardWidth;
    root->height = boardHeight;
    root->down = NULL;
    root->right = NULL;
    root->used = 0;

    totalBlocks = 8;
    blocks = malloc(totalBlocks * sizeof(Block));

    blocks[0] = malloc(sizeof(Block));
    blocks[0]->width = 50;
    blocks[0]->height = 50;
    blocks[0]->id = 0;
    blocks[1] = malloc(sizeof(Block));
    blocks[1]->width = 50;
    blocks[1]->height = 50;
    blocks[1]->id = 1;
    blocks[2] = malloc(sizeof(Block));
    blocks[2]->width = 102;
    blocks[2]->height = 20;
    blocks[2]->id = 2;
    blocks[3] = malloc(sizeof(Block));
    blocks[3]->width = 102;
    blocks[3]->height = 20;
    blocks[3]->id = 3;
    blocks[4] = malloc(sizeof(Block));
    blocks[4]->width = 102;
    blocks[4]->height = 20;
    blocks[4]->id = 4;
    blocks[5] = malloc(sizeof(Block));
    blocks[5]->width = 102;
    blocks[5]->height = 20;
    blocks[5]->id = 5;
    blocks[6] = malloc(sizeof(Block));
    blocks[6]->width = 102;
    blocks[6]->height = 20;
    blocks[6]->id = 6;
    blocks[7] = malloc(sizeof(Block));
    blocks[7]->width = 500;
    blocks[7]->height = 350;
    blocks[7]->id = 7;

    // Bubble Sort
    for (i = 0; i < totalBlocks; i++) {         
        for (j = 0; j < totalBlocks - i - 1; j++) {
            int maxJ = MAX(blocks[j]->height, blocks[j]->width);
            int minJ = MIN(blocks[j]->height, blocks[j]->width);

            int maxJ1 = MAX(blocks[j + 1]->height, blocks[j + 1]->width);
            int minJ1 = MIN(blocks[j + 1]->height, blocks[j + 1]->width);

            if (maxJ < maxJ1) {
                Block *b = blocks[j];
                blocks[j] = blocks[j + 1];
                blocks[j + 1] = b;
            }
            else if (maxJ == maxJ1 && minJ < minJ1) {
                Block *b = blocks[j];
                blocks[j] = blocks[j + 1];
                blocks[j + 1] = b;
            }
        }
    }
    // FIT
    for (i = 0; i < totalBlocks; i++) {
        Block *block = blocks[i];
        Node *node;
        Node * auxNode = root;
        printf("=======================================================");
        print2D(auxNode, 0);
        if (node = findNode(root, block->width, block->height)) {   
            block->fit = splitNode(&node, block->width, block->height);
        }
    }

    for (i = 0; i < totalBlocks; i++) {
        Block *block = blocks[i];
        if (block->fit != NULL) {
            printf("x %d y %d\n", block->fit->x, block->fit->y);
            printf("w %d h %d\n", block->width, block->height);
            printf("\n");
        }
    }


    return 0;
}

Node *findNode(Node *root, int w, int h) {

    if (root->used == 1) {
        Node * rightNode = findNode(root->right, w, h);
        Node * downNode = findNode(root->right, w, h);
         if (rightNode != NULL)
            return rightNode;
        return findNode(root->down, w, h);
    }
    else if ((w <= root->width) && (h <= root->height)) {
        return root;
    }
    else {
        return NULL;
    }
}

Node *splitNode(Node **node, int w, int h) {

    (*node)->used = 1;

    (*node)->down = malloc(sizeof(Node));
    (*node)->down->parent = (*node);
    (*node)->down->down = NULL;
    (*node)->down->right = NULL;
    (*node)->down->x = (*node)->x;
    (*node)->down->y = (*node)->y + h;
    (*node)->down->width = (*node)->width;
    (*node)->down->height = (*node)->height - h;
    (*node)->down->used = 0;

    (*node)->right = malloc(sizeof(Node));
    (*node)->right->parent = (*node);
    (*node)->right->down = NULL;
    (*node)->right->right = NULL;
    (*node)->right->x = (*node)->x + w;
    (*node)->right->y = (*node)->y;
    (*node)->right->width = (*node)->width - w;
    (*node)->right->height = (*node)->height;
    (*node)->right->used = 0;

    return *node;
}

int MAX(int a, int b) {
    return (a > b) ? a : b;
}
int MIN(int a, int b) {
    return (a < b) ? a : b;
}

void print2D(Node *root, int space)
{
    // Base case 
    if (root == NULL)
        return;

    // Increase distance between levels 
    space += COUNT;

    // Process right child first 
    print2D(root->right, space);

    // Print current node after space 
    // count 
    printf("\n");
    for (int i = COUNT; i < space; i++)
        printf(" ");
    printf("(w%d h%d)\n", root->width, root->height);

    // Process left child 
    print2D(root->down, space);
}

Выходы обоих кодов:

Выход моего кода будет:
Изображение 174551

В то время как выход кода javascript с теми же образцами будет: Изображение 174551

** Числа - это координаты (x, y) каждого блока в верхнем левом углу (где есть красная точка). Я сделал это для лучшей визуализации различных результатов.

Ошибка:

Как вы можете видеть на выходном изображении javascript, я рисую красные контуры, где мои последние 3 блока находятся в моем коде, а в javascript - слева, и здесь ошибка. В моем коде блоки также должны быть размещены слева.
Например, последний блок в моем коде имеет координаты 408, 400 а в javascript - 50, 390.

Мои попытки:

Поскольку это двоичное дерево, для его отладки я сделал функцию показа отображения, и вот что я обнаружил:

Изображение 174551

В алгоритме это сделано специально для того, чтобы всегда переходить к rightNode а после этого переходить на downNode, но в моем коде он идет на downNode узел неправильного узла. Пока в javascript идет все так, как задумано.

Решения?

Я делаю это в течение нескольких дней, и меня сводит с ума то, что коды выглядят одинаково, та же логика. Итак, если такая же логика, почему она не работает? Я думаю, что высокий уровень JavaScript делает то, чего не делает мой C-код...

  1. Что высокоуровневый javascript делает под капотом, чтобы перейти на правильный узел, чего не делает мой низкий уровень C?
  2. Что делать, чтобы решить эту проблему?
Теги:
algorithm

1 ответ

1
Лучший ответ

Я думаю, что у вас есть ошибка в вашем коде:

Node *findNode(Node *root, int w, int h) {

    if (root->used == 1) {
        Node * rightNode = findNode(root->right, w, h);
        Node * downNode = findNode(root->right, w, h);  //THIS LINE IS WRONG
         if (rightNode != NULL)
            return rightNode;
        return findNode(root->down, w, h);
    }
    else if ((w <= root->width) && (h <= root->height)) {
        return root;
    }
    else {
        return NULL;
    }
}

По сравнению с оригинальной JS линия должна быть:

Node * downNode = findNode(root->down, w, h);

Хорошо, теперь, когда это исправлено, вот еще один шаг, чтобы исправить это.

см. следующий код

Node *splitNode(Node **node, int w, int h) {

    (*node)->used = 1;

    (*node)->down = malloc(sizeof(Node));
    (*node)->down->parent = (*node);
    (*node)->down->down = NULL;
    (*node)->down->right = NULL;
    (*node)->down->x = (*node)->x;
    (*node)->down->y = (*node)->y + h;
    (*node)->down->width = (*node)->width;
    (*node)->down->height = (*node)->height - h;
    (*node)->down->used = 0;

    (*node)->right = malloc(sizeof(Node));
    (*node)->right->parent = (*node);
    (*node)->right->down = NULL;
    (*node)->right->right = NULL;
    (*node)->right->x = (*node)->x + w;
    (*node)->right->y = (*node)->y;
    (*node)->right->width = (*node)->width - w;
    (*node)->right->height = (*node)->height;   //THIS LINE
    (*node)->right->used = 0;

    return *node;
}

см. отмеченную строку. Это должно быть (я думаю)

(*node)->right->height = h;

(JS имеет h:h не h:node.h)

  • 0
    о, извините, я на самом деле немного изменил свой код, чтобы поместить его здесь, и это было просто ошибкой, я просто изменил его на Node * downNode = findNode(root->down, w, h); и это то же самое.
  • 1
    Хорошо, я продолжу тыкать, чтобы увидеть, смогу ли я найти что-нибудь еще.
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню