- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我一直在做一项作业,涉及实现包含空指针的队列,以便它们可以针对任何类型的数据进行泛化。我目前遇到一个奇怪的问题,虽然出队节点减少了列表的大小但没有返回我期望的节点。在出列操作中省略对 free() 的调用可以纠正这一点,但因为我想释放出列节点,所以这是不可取的。有什么建议吗?
测试运行:routine.c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "queue.h"
int main() {
queue test = make_queue();
enqueue("One", test);
enqueue("Two", test);
printf("Item is %s!\n", (char *)dequeue(test));
printf("Item is %s!\n", (char *)dequeue(test));
return 0;
}
queue.h
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
/* A queue is implemented as a pointer to a structure not specified here. */
typedef struct queue_structure *queue;
struct node {
struct node * next;
void * data;
};
struct queue_structure {
struct node * head;
struct node * tail;
};
/* List of function protocols. */
bool is_empty_queue(queue q);
/* The make_queue function returns a newly created queue with no values
stored in it.
*/
queue make_queue() {
queue newQueue = malloc(sizeof(struct queue_structure));
return newQueue;
}
/* The enqueue function adds a value to a queue. Although this function
does not change the pointer q, fields of the structure to which q
points may be modified in the course of a call to this function.
*/
void enqueue(void *value, queue q) {
struct node * newNode = (struct node *)malloc(sizeof(struct node));
newNode->data = value;
if(is_empty_queue(q))
q->tail = newNode;
newNode->next = q->head;
q->head = newNode;
}
/* The dequeue function removes a value from a queue and returns it.
Although this function does not change the pointer q, fields of the
structure to which q points may be modified in the course of a call to
this function.
It is a precondition of this function that at least one value is stored
in the queue.
*/
void *dequeue(queue q) {
if(!q->head->next) { // Only a single item in the queue.
printf("Only one item in queue!\n");
struct node * to_dequeue = q->tail;
void * data = q->head->data;
free(to_dequeue);
q->head = NULL;
q->tail = NULL;
return data;
}
else { // Multiple items in the queue.
printf("Several items in queue!\n");
struct node * to_dequeue = q->tail;
void * data = q->tail->data;
struct node * trace = q->head;
while(trace->next && trace->next != q->tail)
trace = trace->next;
free(to_dequeue);
q->tail = trace;
q->tail->next = NULL;
return data;
}
}
/* The front_of_queue function returns the value at the front of a queue
(that is, the one least recently added to the queue) without removing
that value from the queue. It has no side effect.
It is a precondition of this function that at least one value is stored
in the queue.
*/
void *front_of_queue(queue q) {
return q->head->data;
}
/* The is_empty_queue function determines whether a queue is empty,
returning the true Boolean value if no values are stored in the queue
and the false Boolean value if one or more values are stored in the
queue.
*/
bool is_empty_queue(queue q) {
if(q->head)
return 1;
return 0;
}
最佳答案
您没有在 make_queue
中将 head
和 tail
初始化为 NULL
并且您已经进行了空性测试错了,
bool is_empty_queue(queue q) {
if(q->head)
return 1;
return 0;
}
这使得 enqueue
行为异常。
void enqueue(void *value, queue q) {
struct node * newNode = (struct node *)malloc(sizeof(struct node));
newNode->data = value;
if(is_empty_queue(q))
q->tail = newNode;
newNode->next = q->head;
q->head = newNode;
}
情况 1,可能 head
和 tail
最初是 NULL
head -> 0; tail -> 0 // now enqueue 1
is_empty_queue(q) returns 0 since q->head == NULL, so q->tail still points to 0
n(1)->next = 0
head = n(1)
results in
head -> n(1) -> 0; tail -> 0 // next enqueue 2
is_empty_queue(q) returns 1 since q->head = n(1) != 0, so
q->tail = n(2)
n(2)->next = n(1)
q->head = n(2)
result:
head -> n(2) -> n(1) -> 0; tail -> n(2)
所有进一步的入队
操作将离开head == tail
。但是,如果您现在 dequeue
:
struct node * to_dequeue = q->tail; // n(2)
void * data = q->tail->data;
struct node * trace = q->head; // n(2)
while(trace->next && trace->next != q->tail) // n(2) -> n(1) -> 0
trace = trace->next; // trace = n(1)
free(to_dequeue); // free n(2)
q->tail = trace; // tail -> n(1)
q->tail->next = NULL; // already had that
head
是一个悬挂指针。
情况 2,可能 head
最初不是 NULL
。
head -> x; tail -> y // enqueue 1
is_empty_queue(q) returns 1 because q->head == x != 0
q->tail = n(1)
n(1)->next = x
q->head = n(1)
head -> n(1) -> x; tail -> n(1) // now enqueue 2
is_empty_queue(q) returns 1 because q->head == n(1)
q->tail = n(2)
n(2)->next = n(1)
q->head = n(2)
head -> n(2) -> n(1) -> x; tail -> n(2)
唯一的区别是现在 n(1)->next != 0
,然后如果你出队,trace
将被设置为野外“指针”x
然后检查 x->next
,但由于 x
是不确定的位模式,这通常会导致段错误。
除非我忽略了一些东西,在构造时初始化 head
和 tail
,修复 is_empty_queue
并检查 dequeue
是否为空> 会给你一个工作计划。
但是如果队列很长,出队操作会很慢,因为它必须遍历整个队列才能找到倒数第二个元素来更新tail
。你可以同时拥有enqueue
和dequeue
,如果你在tail
位置入队和dequeue
,O(1)操作> 来自 head
。
关于c - 排队/出队奇怪?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9029323/
我在使用带有 vector STL 的迭代器时遇到了这个错误。 代码:- #include #include void print_vec(std::vector vec) { auto
JAVA:两个引用“p”&&“pp”之间有区别吗? PrintStream p = new PrintStream(System.out); p.println("lol");
我尝试从主分支中拉出,但收到错误消息: $ git --no-optional-locks -c color.branch=false -c color.diff=false -c color.sta
我面临着一个让我抓狂的问题! 我有一个函数,这个: void load_weapons3(t_env *e, char *name, int x, t_weapon *w) { char
我正在尝试使用 CUDA 中的最小值、最大值、总和和平均值实现并行归约。 这是我目前的主要代码片段。 int main() { const auto count = 8; const
我知道 double free 或 corruption 错误通常是对 big 3 的违规,但在这种情况下,我找不到违规发生的地方。我有一个复制构造函数、析构函数和赋值运算符,适用于任何处理指针的东西
GTK+ 中的“focus”和“focus-in(out)-event”信号有什么区别?哪个先发射?它们与键盘(TAB)和鼠标点击有什么关系。他们互相依赖吗? 我问这个是因为我想在顶层窗口中跟踪当前聚
*** glibc detected *** /home/ghoshs/workspace/Simulator/Debug/Simulator: double free or corruption (
#include #include #include #include using namespace std; #define MAX_WEIGHT 1000000 class Set {
我在服务器上有两个分支一个叫 R2 的分支和一个叫 DEV 的分支我无意中登录了错误的服务器,进入了存储库并执行了GIT pull 源开发但是存储库在 R2 上。所以我意识到我的错误然后尝试通过做一个
我有一个包含循环的大约 1000 个顶点和 3000 个边的有向图。 我试图从给定的顶点找到所有下游(出)路径。 使用以下 Gremlin 查询时 g.V(45712).repeat(out().si
使用 Delphi XE 2 我试图确定缩放方向以将缩放效果应用于图像(TImage),但没有找到执行此操作的函数,并且图像的 OnGesture 事件中的 EventInfo 属性没有此信息. 我见
我正在尝试创建一个 Zoom_image 函数,它使用离散傅里叶变换来缩放灰度图像。如果图像大小小于或等于 4*4 但大小增加,我包含的代码可以工作。它给出“双重释放或损坏(出)中止(核心转储)”错误
当我执行 popAll 函数时,出现以下错误: 双重释放或腐败(出)中止(核心转储) 我想我已经将错误来源缩小到了这个函数。 IntegerStack 是我制作的一个简单的 ADT,其中包含一个名为
我有网络开发背景,我正在尝试创建类似于 this technique 的东西适用于 iOS(使用 Cocoa/Obj C)。我在谷歌搜索资源时遇到了很多困难,因为 iOS 中的“视差”往往指的是 iO
我想实现一个 faceted search对于我的一个项目。我正在使用 PHP5、Mysql 和 Symfony 1.4。显然社区指向Apache Solr这似乎正是我想要完成的。 问题是该网站将在不
我知道有 questions floating around当您没有提供明确的分支名称时,关于来自特定分支的 git pull,但是我想知道即使用户确实指定了不同的分支,是否也可以强制 pull 分支
我正在尝试将我的更改推送到 NAS 上的存储库。它以我无法理解的方式失败。 documentation声明默认情况下 push 仅适用于快进更新。很公平。所以我做了一个 git pull(我的 Rem
我刚开始使用 Oracle 的 Coherence 缓存,我注意到这一点:如果我在缓存中放入一个 ConcurrentHashMap 对象,当我检索它时,我可以看到它被转换为一个普通的 HashMap
我尝试创建一个连接到数据库的线程,从那里获取一些数据并打印到控制台。问题是当该线程完成时抛出异常: 双重免费或腐败(出局)中止(核心转储) 我尝试使用 sqlite3 和 pthread,但这两个并不
我是一名优秀的程序员,十分优秀!