我正在尝试在C中设置一个双端指针队列。 到目前为止,我已经将推送功能工作和测试。我的问题似乎与两端的弹出条目有关。
#include <stdlib.h>
#include <stdio.h>
#include "dequeue.h"
dequeue* dequeue_create()
{
return NULL;
}
void dequeue_push_front(dequeue** dq, int data)
{
dequeue* tmp = malloc(sizeof(*tmp));
tmp->data = data;
tmp->next=NULL;
if((*dq) == NULL)
{
(*dq) = tmp;
}
else
{
if ((*dq)->next == NULL)
{
(*dq)->next = tmp;
tmp->prev = (*dq);
}
else
{
dequeue* tmp_it = malloc(sizeof(struct _dequeue_));
tmp_it = (*dq)->next;
while(tmp_it->next != NULL)
{
tmp_it = tmp_it->next;
}
tmp_it->next = tmp;
tmp->prev = tmp_it;
}
}
}
void dequeue_push_back(dequeue** dq, int data)
{
dequeue* tmp = malloc(sizeof(struct _dequeue_));
tmp->data = data;
tmp->prev=NULL;
if((*dq) == NULL)
{
(*dq) = tmp;
}
else
{
if ((*dq)->prev == NULL)
{
(*dq)->prev = tmp;
tmp->next = (*dq);
}
else
{
dequeue* tmp_it = malloc(sizeof(struct _dequeue_));
tmp_it = (*dq)->prev;
while(tmp_it->prev != NULL)
{
tmp_it = tmp_it->prev;
}
tmp_it->prev = tmp;
tmp->next = tmp_it;
}
}
}
int dequeue_pop_front(dequeue** dq)
{
dequeue* tmp_get = malloc(sizeof(struct _dequeue_));
int output = 0;
if((*dq)->next == NULL)
{
printf("\ndqnext==null\n");
}
else
{
tmp_get = (*dq);
while(tmp_get->next != NULL)
{
tmp_get= tmp_get->next;
output = tmp_get->data;
}
tmp_get=tmp_get->prev;
free(tmp_get->next);
tmp_get->next=NULL;
}
return output;
}
int dequeue_pop_back(dequeue** dq)
{
dequeue* tmp_get = malloc(sizeof(struct _dequeue_));
int output = 0;
if((*dq)->prev == NULL)
{
printf("\ndqprev==null\n");
}
else
{
tmp_get = (*dq);
while(tmp_get->prev != NULL)
{
output = tmp_get->data;
tmp_get= tmp_get->prev;
}
free(tmp_get);
tmp_get=NULL;
}
return output;
}
dequeue.h:
#ifndef dequeue_H
#define dequeue_H
struct _dequeue_ {
struct _dequeue_* next;
struct _dequeue_* prev;
int data;
};
typedef struct _dequeue_ dequeue;
dequeue* dequeue_create();
void dequeue_destroy(dequeue** queue);
int dequeue_pop_front(dequeue** dq);
void dequeue_push_front(dequeue** dq, int data);
int dequeue_pop_back(dequeue** dq);
void dequeue_push_back(dequeue** dq, int data);
#endif /* dequeue_H */
main.c中:
int main()
{
dequeue* dq = dequeue_create();
dequeue_push_front(&dq, 1);
dequeue_push_back(&dq, 2);
dequeue_push_front(&dq, 3);
for (int cnt = 1; cnt <=4; cnt++)
{
printf("FINAL=%d ", dequeue_pop_front(&dq));
}
//TODO : dequeue_destroy(&dq);
return 0;
}
我对指针很新,这似乎是我的问题。
我在pop函数中尝试做的是迭代指针以到达最后一个并释放最后一个指针。但它似乎没有释放指针。现在尝试了几种不同的方法,但似乎没有一种方法可行,可能是我设置推送功能的方式是不可能释放指针吗?
任何帮助非常感谢。 欢呼声
答案 0 :(得分:0)
dequeue_push_front(&dq, 1);
NULL&lt; - middle(1) - &gt; NULL
dq
指向中间节点
dequeue_push_front(&dq, 2);
NULL&lt; - middle(1)&lt; - &gt;右(2) - &gt; NULL
dq
仍然指向中间节点,因为只有在dq
传递NULL
NULL&lt; - left(3)&lt; - &gt;中(1)&lt; - &gt;右(2) - &gt; NULL
dq
仍指向中间节点的原因相同
让我们按照你的流行代码:
tmp_get = (*dq);
while(tmp_get->next != NULL)
{
tmp_get= tmp_get->next;
output = tmp_get->data;
}
tmp_get=tmp_get->prev;
free(tmp_get->next);
tmp_get->next=NULL;
这导致以下状态:
NULL&lt; - left(3)&lt; - &gt;中(1) - &gt; NULL
dq
仍指向中间节点。下一步,每隔一次执行该功能
if((*dq)->next == NULL)
将评估为真,导致无法进一步更改。
如评论中所述,pop函数中存在内存泄漏。见下文:
dequeue* tmp_get = malloc(sizeof(struct _dequeue_));
...
tmp_get = (*dq);
调用 malloc()
,分配sizeof(struct _dequeue_)
个字节的内存。返回一个指针,并将其分配给变量tmp_get。然后用不同的指针覆盖此指针,这意味着现在有一块您无法访问或释放的已分配内存块。我无法看到你为什么需要首先分配这个内存的原因。
答案 1 :(得分:0)
在深入研究实际问题之前的一些提示:
然后,有一些误解:你的_dequeue_s是一个出队的NODES但不是一个出队本身。所以,你应该有两个结构:
struct dequeue_node {
struct dequeue_node * next;
struct dequeue_node * prev;
int data;
};
struct dequeue {
struct dequeue_node * frst;
struct dequeue_node * last;
size_t size;
};
首先调用条目(而不是第一个)是我的个人风格,它使其长度为4个字符,如next / prev / last / size,但如果您愿意,可以先调用它。不需要大小但允许O(1)检索出队的大小。
通过这种方式,你不必走遍整个队列就能找到它。
所以,现在你的实际问题是:
创建第一个节点时,dequeue_push_front不会初始化tmp-&gt; prev(并且dequeue_push_back不会初始化tmp-&gt; next)。所以,你从一开始就出列了非法国家。
然后,当我想到&#34;前面&#34;时,我想到&#34;首先&#34;并假设有下一个。所以,差不多,你要交换next和prev的含义。假设这一个:
a b c
+-------------+ +-------------+ +-------------+
| next = b | | next = c | | next = NULL |
| prev = NULL | | prev = a | | prev = b |
+-------------+ +-------------+ +-------------+
我会打电话给#34;第一个&#34;和c&#34;最后&#34;。但是dequeue_push_front试图在这个ascii艺术中添加一个c元素。
鉴于您的命名,推送功能似乎是正确的(除了上述要点)。
pop函数现在有一个错误, s.b已经注意到了。谁再次删除了他的帖子 Ben Wainwright(他编辑,显示为删除后)。你检查(* dp) - &gt; next / prev == NULL,如果这是真的,你要拯救,但你应该删除该节点。所以对于dequeue_pop_front(在你的实现中):
if ((*dq)->next == NULL) {
dequeue * tmp = (*dq);
output = tmp->data;
(*dq) = (*dq)->prev;
if ((*dq)) {
(*dq)->next = NULL;
}
free(tmp);
} else {
...
并且在pop_back中反之亦然。
其余的问题是效率低下和内存泄漏,对于后者你应该学会使用http://valgrind.org/来找到它们,而对于第一个,你应该总是问自己,天气声明可以移出一个循环,就像这里:(再次来自dequeue_pop_front):
while(tmp_get->next != NULL)
{
tmp_get= tmp_get->next;
output = tmp_get->data; // this can be moved out
}
输出变量将不断被覆盖,直到循环结束,因此,将其输出:
while(tmp_get->next != NULL)
{
tmp_get= tmp_get->next;
}
output = tmp_get->data; // this can be moved out
所以,最终的dequeue.c(但你应该用dequeue&amp; dequeue_node进行更改):
dequeue* dequeue_create()
{
return NULL;
}
void dequeue_push_front(dequeue** dq, int data)
{
dequeue* tmp = malloc(sizeof(*tmp));
tmp->data = data;
tmp->next=NULL;
tmp->prev=NULL;
if((*dq) == NULL)
{
(*dq) = tmp;
}
else
{
if ((*dq)->next == NULL)
{
(*dq)->next = tmp;
tmp->prev = (*dq);
}
else
{
dequeue* tmp_it = malloc(sizeof(struct _dequeue_));
tmp_it = (*dq)->next;
while(tmp_it->next != NULL)
{
tmp_it = tmp_it->next;
}
tmp_it->next = tmp;
tmp->prev = tmp_it;
}
}
}
void dequeue_push_back(dequeue** dq, int data)
{
dequeue* tmp = malloc(sizeof(struct _dequeue_));
tmp->data = data;
tmp->next=NULL;
tmp->prev=NULL;
if((*dq) == NULL)
{
(*dq) = tmp;
}
else
{
if ((*dq)->prev == NULL)
{
(*dq)->prev = tmp;
tmp->next = (*dq);
}
else
{
dequeue* tmp_it = malloc(sizeof(struct _dequeue_));
tmp_it = (*dq)->prev;
while(tmp_it->prev != NULL)
{
tmp_it = tmp_it->prev;
}
tmp_it->prev = tmp;
tmp->next = tmp_it;
}
}
}
int dequeue_pop_front(dequeue** dq)
{
dequeue* tmp_get = malloc(sizeof(struct _dequeue_));
int output = 0;
if((*dq)->next == NULL)
{
dequeue * tmp = (*dq);
output = tmp->data;
(*dq) = (*dq)->prev;
if ((*dq)) {
(*dq)->next = NULL;
}
free(tmp);
}
else
{
tmp_get = (*dq);
while(tmp_get->next != NULL)
{
tmp_get= tmp_get->next;
output = tmp_get->data;
}
tmp_get=tmp_get->prev;
free(tmp_get->next);
tmp_get->next=NULL;
}
return output;
}
int dequeue_pop_back(dequeue** dq)
{
dequeue* tmp_get = malloc(sizeof(struct _dequeue_));
int output = 0;
if((*dq)->prev == NULL)
{
dequeue * tmp = (*dq);
output = tmp->data;
(*dq) = (*dq)->next;
if ((*dq)) {
(*dq)->prev = NULL;
}
free(tmp);
}
else
{
tmp_get = (*dq);
while(tmp_get->prev != NULL)
{
output = tmp_get->data;
tmp_get= tmp_get->prev;
}
free(tmp_get);
tmp_get=NULL;
}
return output;
}