Я пытаюсь воспроизвести этот Алгоритм в C, Packing Blocks into a Fixed Rectangle
и я уже задаю вопрос об этом, но все еще не получаю те же результаты. Я нашел конкретный ввод, который вызывает "ошибку", и, чтобы показать, что я статически устанавливаю значения в коде, чтобы облегчить его тестирование.
#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);
}
Выход моего кода будет:
В то время как выход кода javascript с теми же образцами будет:
** Числа - это координаты (x, y) каждого блока в верхнем левом углу (где есть красная точка). Я сделал это для лучшей визуализации различных результатов.
Как вы можете видеть на выходном изображении javascript, я рисую красные контуры, где мои последние 3 блока находятся в моем коде, а в javascript - слева, и здесь ошибка. В моем коде блоки также должны быть размещены слева.
Например, последний блок в моем коде имеет координаты 408, 400
а в javascript - 50, 390
.
Поскольку это двоичное дерево, для его отладки я сделал функцию показа отображения, и вот что я обнаружил:
В алгоритме это сделано специально для того, чтобы всегда переходить к rightNode
а после этого переходить на downNode
, но в моем коде он идет на downNode
узел неправильного узла. Пока в javascript идет все так, как задумано.
Я делаю это в течение нескольких дней, и меня сводит с ума то, что коды выглядят одинаково, та же логика. Итак, если такая же логика, почему она не работает? Я думаю, что высокий уровень JavaScript делает то, чего не делает мой C-код...
Я думаю, что у вас есть ошибка в вашем коде:
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
)
Node * downNode = findNode(root->down, w, h);
и это то же самое.