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); } }
我认为最好使用像我在这里发布的代码中那样更简单的方法 下面几行中的代码与竞赛所需的输入/输出不匹配,但包含了一种解决问题的功能简单的方法:一个简单的堆栈管理器!(如果我理解正确的话)
触发问题的确切输入是什么?@MichaelWalz未显示):。当查看测试列表时,前26个测试给出了#包括 #包括 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; }
,平均执行时间为2ms,(我猜)内存使用率为380.00Kb。最后一个测试给出了ok
,执行时间为98ms,内存使用量为5.14Mb。我告诉您,要处理此类问题,不需要管理链表。您不需要节点。管理指向内存区域的指针并将其复制到“基本指针”中就足够了。当您按下一个值时,您在内存中设置一个值并增加内存指针;当您弹出该值时,您减少内存指针并读取该值。当内存指针等于“基指针”时,堆栈中没有任何内容。在PushBack()中,看起来您正在覆盖值。您需要转到列表的开头/结尾,然后添加新分配的节点。@MayurK,被覆盖的“值”是用于操作的指针MLE
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; }