Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C:超出队列和内存限制_C_Data Structures_Queue - Fatal编程技术网

C:超出队列和内存限制

C:超出队列和内存限制,c,data-structures,queue,C,Data Structures,Queue,我是一名C初学者,为了练习,我决定参加一个小型的在线比赛 在当前问题中,我被要求编写一个带有struct的队列,该队列响应命令PushBack和PopFront 输入包括 一个数字n(n我不认为该代码在功能上有任何问题,尽管它可能与一些格式改进有关:-) 我要提一件事: 任务是检查执行PopFront后返回的值是否与预期值一致。如果是,则打印YES。打印否,否则 我认为这是每个PopFront的一个要求。您似乎正在存储故障条件,并且在最后只打印一次YES或NO 我建议先解决这个问题,然后看看在

我是一名
C
初学者,为了练习,我决定参加一个小型的在线比赛

在当前问题中,我被要求编写一个带有
struct
的队列,该队列响应命令
PushBack
PopFront

输入包括


  • 一个数字
    n
    n我不认为该代码在功能上有任何问题,尽管它可能与一些格式改进有关:-)

    我要提一件事:

    任务是检查执行
    PopFront
    后返回的值是否与预期值一致。如果是,则打印
    YES
    。打印
    ,否则

    我认为这是每个
    PopFront
    的一个要求。您似乎正在存储故障条件,并且在最后只打印一次
    YES
    NO

    我建议先解决这个问题,然后看看在线法官会带什么回来


    这一切都忽略了一个事实,即除非您能够重现问题,否则调试代码实际上相当困难。如果您无法从在线竞赛中获得数据集,那么您可能需要生成自己的(大型)数据集,以查看您是否可以让代码失败

    一旦出现可重复的故障,调试就会变得非常容易


    虽然这不太可能,但您可能(正如mch在评论中指出的那样)正在与有限的内存发生冲突。我认为这是不可能的,因为你自己的评论表明,只有5MEG的空间正在使用,这并不繁重。然而,如果是这样的话,可能是因为每个整数都有一个指针的开销

    如果您想调查这一途径,您可以稍微调整以下结构(同时去掉不必要的
    计数器
    ):

    其思想是在每个节点上存储许多项,以便大大减少
    next
    指针的开销(每千项一个指针,而不是每项一个指针)

    队列操作的代码将变得稍微复杂一些,但仍然可以理解。首先,是一个用于创建新节点的辅助函数,可将数据添加到:

    // Helper to allocate a new node and prep it for appending.
    // Returns node or NULL (and prints error) if out of memory.
    
    Node *GetNewNode(void) {
        Node *pnode = malloc (sizeof(Node));
        if (pnode == NULL)
            fputs ("Impossible to allocate memory", stderr);
        else
            pnode->startIndex = pnode->nextIndex = 0;
        return pnode;
    }
    
    接下来,基本不变的队列初始化:

    void InitializeQueue (Queue *pq) {
        pq->front = pq->rear = NULL;
    }
    
    推送稍微复杂一些,因为如果队列为空或当前最后一个节点已到达末尾,它首先添加一个新的多项目节点。无论是否发生这种情况,都会将项目添加到最终节点:

    bool PushBack (Queue *pq, Item item) {
        // Default to adding to rear node (assuming space for now).
    
        Node *pnode = pq->rear;
    
        // Make sure queue has space at end for new item.
    
        if (pq->front == NULL) {
            // Handle empty queue first, add single node.
    
            if ((pnode = GetNewNode()) == NULL)
                return false;
            pq->front = pq->rear = pnode;
    
        } else if (pq->rear->nextItem == ITEMS_PER_NODE) {
            // Handle new node needed in non-empty queue, add to rear of queue.
    
            if ((pnode = GetNewNode()) == NULL)
                return false;
            pq->rear->next = pnode;
            pq->rear = pnode;
        }
    
        // Guaranteed space in (possibly new) rear node now, just add item.
    
        pq->rear->item[pq->rear->nextIndex++] = item;
    }
    
    弹出也有点复杂-它获取要返回的值,然后在第一个节点耗尽时删除它。如果它删除的节点是唯一的节点,则可能还需要清除队列:

    int PopFront (Queue * pq) {
        // Capture empty queue.
    
        if (pq->first == NULL)
            return -1;
    
        // Get value to pop.
    
        Node *currFront = pq->front;
        int valuePopped = currFront->item[currFront->startIndex++];
    
        // Detect current node now empty, delete it.
    
        if (currFront->startItem == currFront->endIndex) {
            // Detect last node in queue, just free and empty entire queue.
    
            if (currFront == pq->rear) {
                free (currFront);
                pq->front = pq->rear = NULL;
            } else {
                // Otherwise remove front node, leaving others.
    
                pq->front = currFront->next;
                free (currFront);
            }
        }
    
        // Regardless of queue manipulation, return popped value.
    
        return valuePopped;
    }
    
    清空队列在很大程度上没有变化,只是我们清除了节点而不是项目:

    void EmptyQueue (Queue * pq) {
        // Can empty node at a time rather than item at a time.
    
        while (pq->front != NULL) {
            Node *currentFront = pq->front;
            pq->front = pq->front->next;
            free (currentFront);
        }
    }
    

    我认为最好使用像我在这里发布的代码中那样更简单的方法

    下面几行中的代码与竞赛所需的输入/输出不匹配,但包含了一种解决问题的功能简单的方法:一个简单的堆栈管理器!(如果我理解正确的话)

    #包括
    #包括
    int*堆栈;
    整数*基数;
    int-cnt;
    /*模拟输入文件*/
    结构stFile{
    int n;
    结构stCmd{
    INTA;
    int b;
    }cmd[200];//200是一个任意值。
    }fdata={
    20,
    {
    {2,0},
    {2,0},
    {2,0},
    {3,35},
    {2,0},
    {3,4},
    {2,0},
    {2,0},
    {2,0},
    {3,12},
    {3,15},
    {3,8},{3,18},
    {2,0},
    {2,0},
    {3,111},
    {2,0},
    {2,0},
    {2,0},
    {2,0},
    {3,8},{3,18},{3,8},{3,18},{3,8},{3,18},{3,8},{3,18},{3,8},{3,18},
    {3,11},{3,13},{3,11},{3,11},{3,11},{3,11},{3,11},{3,11},
    {3,11},{3,13},{3,11},{3,11},{3,11},{3,11},{3,11},{3,11},
    {2,0},
    {2,0},
    {2,0},
    {2,0},
    {2,0},
    {2,0},
    {2,0},
    {2,0},
    {0,0}
    }
    };
    整数推送(整数项)
    {
    如果(cnt){
    *堆栈=项目;
    stack++;
    碳纳米管;
    返回0;
    }否则{
    返回1;
    }
    }
    int-pop(int*empty)
    {
    如果(堆栈!=基础){
    堆栈--;
    cnt++;
    if(空)
    *空=0;
    }否则{
    if(空)
    *空=1;
    }
    返回*堆栈;
    }
    内部主(空)
    {
    int i=0,e=0;
    cnt=fdata.n;
    base=stack=malloc(cnt*sizeof(int));
    如果(!base){
    放置(“内存不足!”);
    返回1;
    }
    while(fdata.cmd[i].a!=0){
    开关(fdata.cmd[i].a){
    案例2:
    printf(“弹出…:%d”,弹出(&e));
    printf(“空的:%d\n”,e);
    打破
    案例3:
    e=push(fdata.cmd[i].b);
    printf(“推送…:%d%s\n”,fdata.cmd[i].b,(e)?“未推送”:“推送”);
    打破
    违约:
    打破
    };
    i++;
    }
    如果(基本)
    自由(基本);
    返回0;
    }
    
    触发问题的确切输入是什么?@MichaelWalz未显示):。当查看测试列表时,前26个测试给出了
    ok
    ,平均执行时间为2ms,(我猜)内存使用率为380.00Kb。最后一个测试给出了
    MLE
    ,执行时间为98ms,内存使用量为5.14Mb。我告诉您,要处理此类问题,不需要管理链表。您不需要节点。管理指向内存区域的指针并将其复制到“基本指针”中就足够了。当您按下一个值时,您在内存中设置一个值并增加内存指针;当您弹出该值时,您减少内存指针并读取该值。当内存指针等于“基指针”时,堆栈中没有任何内容。在PushBack()中,看起来您正在覆盖值。您需要转到列表的开头/结尾,然后添加新分配的节点。@MayurK,被覆盖的“值”是用于操作的指针
    int PopFront (Queue * pq) {
        // Capture empty queue.
    
        if (pq->first == NULL)
            return -1;
    
        // Get value to pop.
    
        Node *currFront = pq->front;
        int valuePopped = currFront->item[currFront->startIndex++];
    
        // Detect current node now empty, delete it.
    
        if (currFront->startItem == currFront->endIndex) {
            // Detect last node in queue, just free and empty entire queue.
    
            if (currFront == pq->rear) {
                free (currFront);
                pq->front = pq->rear = NULL;
            } else {
                // Otherwise remove front node, leaving others.
    
                pq->front = currFront->next;
                free (currFront);
            }
        }
    
        // Regardless of queue manipulation, return popped value.
    
        return valuePopped;
    }
    
    void EmptyQueue (Queue * pq) {
        // Can empty node at a time rather than item at a time.
    
        while (pq->front != NULL) {
            Node *currentFront = pq->front;
            pq->front = pq->front->next;
            free (currentFront);
        }
    }
    
    #include <stdio.h>
    #include <malloc.h>
    
    int * stack;
    int * base;
    int cnt;
    
    /* To emulate input file */
    struct stFile {
        int n;
        struct stCmd {
            int a;
            int b;
        } cmd[200]; // 200 is an arbitrary value.
    } fdata = {
        20,
        {
            {2,0},
            {2,0},
            {2,0},
            {3,35},
            {2,0},
            {3,4},
            {2,0},
            {2,0},
            {2,0},
            {3,12},
            {3,15},
            {3,8},{3,18},
            {2,0},
            {2,0},
            {3,111},
            {2,0},
            {2,0},
            {2,0},
            {2,0},
            {3,8},{3,18},{3,8},{3,18},{3,8},{3,18},{3,8},{3,18},{3,8},{3,18},
            {3,11},{3,13},{3,11},{3,11},{3,11},{3,11},{3,11},{3,11},
            {3,11},{3,13},{3,11},{3,11},{3,11},{3,11},{3,11},{3,11},
            {2,0},
            {2,0},
            {2,0},
            {2,0},
            {2,0},
            {2,0},
            {2,0},
            {2,0},
            {0,0}
        }
    };
    
    int push(int item)
    {
        if (cnt) {
            *stack = item;
            stack++;
            cnt--;
            return 0;
        } else {
            return 1;
        }
    }
    
    int pop(int *empty)
    {
        if (stack!=base) {
            stack--;
            cnt++;
            if (empty)
                *empty = 0;
        } else {
            if (empty)
                *empty = 1;
        }
    
        return *stack;
    }
    
    int main(void)
    {
        int i=0,e=0;
    
        cnt = fdata.n;
        base = stack = malloc(cnt*sizeof(int));
    
        if (!base) {
            puts("Not enough memory!");
            return 1;
        }
    
        while(fdata.cmd[i].a!=0) {
            switch(fdata.cmd[i].a) {
            case 2:
                printf("popping ...: %d ",pop(&e));
                printf("empty: %d\n",e);
                break;
    
            case 3:
                e = push(fdata.cmd[i].b);
                printf("pushing ...: %d %s\n",fdata.cmd[i].b,(e)?"not pushed":"pushed");
                break;
    
            default:
                break;
    
            };
    
            i++;
        }
    
        if (base)
            free(base);
    
        return 0;
    }