C

时间:2018-11-30 11:43:01

标签: javascript c algorithm

背景:

我正在尝试在C语言的Packing Blocks into a Fixed Rectangle部分复制this算法,并且我已经对此做了一个question,该问题的解决方案是正确的,但是没有。 t解决了整体问题。我发现了导致“错误”的特定输入,并表明了这一点,我在代码中静态设置了这些值,以使其易于测试。

我的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);
         if (rightNode != NULL)
            return rightNode;

        Node * downNode = findNode(root->down, w, h);
        return downNode;
    }
    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);
}

两个代码的输出:

我的代码的输出结果是:
 my c code output

具有相同示例的javascript代码的输出为: js output

**数字是左上角(有红点的位置)中每个块的坐标(x,y)。我这样做是为了更好地可视化不同的输出。

错误:

正如您在javascript输出图像中看到的那样,我绘制了红色轮廓,这是我的代码中最后3个块的位置,而在javascript中,它位于左侧,而错误。在我的代码中,这些块也应该放在左侧。
例如我代码中的最后一个块的坐标为408, 400,而JavaScript中的最后一个块为50, 390

我的尝试:

因为这是一棵二叉树,要对其进行调试,我做了一个显示它的函数,这就是我发现的结果:

binary tree display

在算法中,它是故意创建的,总是去rightNode,然后去downNode,但是我的代码却在错误的downNode上进行节点。在javascript中,一切都按预期进行。

解决方案?

我已经这样做了好几天,而令我发疯的是,这些代码看起来相同,逻辑相同。那么,如果逻辑相同,为什么它不起作用? 我认为javascript高水平正在做我的C代码不做的事情...

  1. 要进入我的底层C没做的正确节点,javascript高层到底在做什么?
  2. 该如何解决此问题?

编辑1:

已更改

    Node * rightNode = findNode(root->right, w, h);
    Node * downNode = findNode(root->down, w, h);
    if (rightNode != NULL)
        return rightNode;               
    return downNode;

    Node * rightNode = findNode(root->right, w, h);
    if (rightNode != NULL)
        return rightNode;

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

但仍然存在相同的错误。

1 个答案:

答案 0 :(得分: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