从队列中删除所有项目
Deleting all items from a queue
假设我有以下结构
typedef struct node {
unsigned long data;
struct node* next;
} node;
typedef struct queue {
node* head;
node* tail;
int size;
int capacity;
} queue;
queue* buildar()
{
queue* arr = malloc(num * sizeof(queue));
int i;
for (i = 0; i < num; i++)
{
queue* r = malloc(sizeof(queue));
r->head = NULL;
r->tail = NULL;
r->size = 0;
r->capacity = assoc;
arr[i] = *r;
}
return arr;
}
如何释放队列中的所有项目?
我已经尝试过这样做
for (size_t i = 0; i < numberofsets; i++)
{
node* temp = arr[i].head;
arr[i].head = arr[i].head->next;
free(temp);
}
free(arr);
但它似乎不起作用。感谢任何帮助。
很难猜测“似乎不起作用”是什么意思,但代码存在几个问题。
在buildar()
中你使用了两个未定义的变量。您可能将它们作为全局变量,但您可能希望它们作为函数的参数。您还泄漏了内存,因为您 malloc()
一个新的 link,初始化它,将其中的值复制到数组中,然后丢弃分配的内存,现在将永远不会被释放。
// added num & assoc here--assuming it should be a parameter
queue* buildar(int num, int assoc)
{
queue* arr = malloc(num * sizeof(queue));
int i;
for (i = 0; i < num; i++)
{
// This will leak memory. You allocate a root
// that you initialise, then you copy the data
// and then you throw away the allocated memory
// when you update r, or it goes out of scope
queue* r = malloc(sizeof(queue));
r->head = NULL;
r->tail = NULL;
r->size = 0;
r->capacity = assoc;
arr[i] = *r;
}
return arr;
}
因为你已经在数组中有根 links,你可以只更新它们,避免 malloc()
:
queue* buildar(int num, int assoc)
{
queue* arr = malloc(num * sizeof *arr);
for (int i = 0; i < num; i++)
{
arr[i].head = NULL;
arr[i].tail = NULL;
arr[i].size = 0;
arr[i].capacity = assoc;
}
return arr;
}
在释放代码中,如果根节点是新初始化的,它们的head
指针是NULL
。当您取消引用它们以获取 head->next
时,这将是一个问题。从技术上讲,取消引用 NULL
是未定义的行为,但实际上,这将是一个分段错误,会使您的程序崩溃。如果每个条目有多个节点,则会泄漏内存。你在根之后释放第一个,然后将根的头部指向下一个,然后释放保存根的数组。
据我所知,如果每个索引只有一个节点(在根之后),代码将按预期工作,但如果为零则崩溃,如果有更多则泄漏。如果应该有可变数量的节点,那就是“似乎不起作用”的一个来源。可能是这样吗?
void free_queues(queue *arr, int numberofsets)
{
for (size_t i = 0; i < numberofsets; i++)
{
node* temp = arr[i].head;
// if the queue was empty, arr[i].head->next
// dereferences a NULL pointer, which is
// undefined behaviour
arr[i].head = arr[i].head->next;
// This only removes one link from the queue.
// If there are more, you leak memory when you
// free arr below
free(temp);
}
free(arr);
}
如果是这样的话,您可能需要这样的东西:
void free_queues(queue *arr, int numberofsets)
{
for (size_t i = 0; i < numberofsets; i++) {
node* temp = arr[i].head, *next;
while (temp) {
next = temp->next;
free(temp);
temp = next;
}
}
free(arr);
}
您正在寻找数组的数组(我think/hope)。基本上,您想从一个“主”数组创建 n
全部可索引(这是一个词吗?)的队列。
所以你是这样看的:
idx
of
big
arry
_________________________________
|000| -----> [ one big queue ]
|001| -----> [ one big queue ]
|002| -----> [ one big queue ]
|003| -----> [ one big queue ]
|004| -----> [ one big queue ]
|...| -----> .................
|nth| -----> [ one big queue ]
_________________________________
#include <stdlib.h>
typedef struct node
{
unsigned long data;
struct node* next;
}
node;
typedef struct queue
{
int size;
int capacity;
node* head;
node* tail;
}
queue;
queue** build_queue(int num ,
int assoc
)
{
//here you create an array of arrays
//result is an array of pointers, each pointer going to a separate array
queue** result = malloc(num * sizeof(queue*));
int i;
for (i = 0; i < num; i++)
{
queue* q = malloc(sizeof(queue)); //memory for actual queue
result[i] = q;
q->head = NULL;
q->tail = NULL;
q->size = 0;
q->capacity = assoc;
}
return result;
}
void free_queues(int num_queues,
queue** qs
)
{
int i;
for (i = 0; i < num_queues; i++)
{
/*
* NOTE: you must use a while loop here to FIRST free the linked list qs[i]
* node* head = qs[i]->head;
* while(head != qs[i]->tail)
* {
* node* temp = head->next;
free(head);
head = temp;
* }
* free(qs[i]->tail);
*/
free(qs[i]); //frees the actual queue struct
}
free(qs); //frees the array of pointers to queues
}
int main(void)
{
int num = 5;
int assoc = 4;
queue** qs = build_queue(num, assoc);
free_queues(num, qs);
return 1;
}
最后用valgrind
检查是否有漏水。对于上述解决方案:
$ gcc please_work.c
$ valgrind ./a.out
==5974== Memcheck, a memory error detector
==5974== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==5974== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==5974== Command: ./a.out
==5974==
==5974==
==5974== HEAP SUMMARY:
==5974== in use at exit: 0 bytes in 0 blocks
==5974== total heap usage: 6 allocs, 6 frees, 160 bytes allocated
==5974==
==5974== All heap blocks were freed -- no leaks are possible
==5974==
==5974== For lists of detected and suppressed errors, rerun with: -s
==5974== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
假设我有以下结构
typedef struct node {
unsigned long data;
struct node* next;
} node;
typedef struct queue {
node* head;
node* tail;
int size;
int capacity;
} queue;
queue* buildar()
{
queue* arr = malloc(num * sizeof(queue));
int i;
for (i = 0; i < num; i++)
{
queue* r = malloc(sizeof(queue));
r->head = NULL;
r->tail = NULL;
r->size = 0;
r->capacity = assoc;
arr[i] = *r;
}
return arr;
}
如何释放队列中的所有项目? 我已经尝试过这样做
for (size_t i = 0; i < numberofsets; i++)
{
node* temp = arr[i].head;
arr[i].head = arr[i].head->next;
free(temp);
}
free(arr);
但它似乎不起作用。感谢任何帮助。
很难猜测“似乎不起作用”是什么意思,但代码存在几个问题。
在buildar()
中你使用了两个未定义的变量。您可能将它们作为全局变量,但您可能希望它们作为函数的参数。您还泄漏了内存,因为您 malloc()
一个新的 link,初始化它,将其中的值复制到数组中,然后丢弃分配的内存,现在将永远不会被释放。
// added num & assoc here--assuming it should be a parameter
queue* buildar(int num, int assoc)
{
queue* arr = malloc(num * sizeof(queue));
int i;
for (i = 0; i < num; i++)
{
// This will leak memory. You allocate a root
// that you initialise, then you copy the data
// and then you throw away the allocated memory
// when you update r, or it goes out of scope
queue* r = malloc(sizeof(queue));
r->head = NULL;
r->tail = NULL;
r->size = 0;
r->capacity = assoc;
arr[i] = *r;
}
return arr;
}
因为你已经在数组中有根 links,你可以只更新它们,避免 malloc()
:
queue* buildar(int num, int assoc)
{
queue* arr = malloc(num * sizeof *arr);
for (int i = 0; i < num; i++)
{
arr[i].head = NULL;
arr[i].tail = NULL;
arr[i].size = 0;
arr[i].capacity = assoc;
}
return arr;
}
在释放代码中,如果根节点是新初始化的,它们的head
指针是NULL
。当您取消引用它们以获取 head->next
时,这将是一个问题。从技术上讲,取消引用 NULL
是未定义的行为,但实际上,这将是一个分段错误,会使您的程序崩溃。如果每个条目有多个节点,则会泄漏内存。你在根之后释放第一个,然后将根的头部指向下一个,然后释放保存根的数组。
据我所知,如果每个索引只有一个节点(在根之后),代码将按预期工作,但如果为零则崩溃,如果有更多则泄漏。如果应该有可变数量的节点,那就是“似乎不起作用”的一个来源。可能是这样吗?
void free_queues(queue *arr, int numberofsets)
{
for (size_t i = 0; i < numberofsets; i++)
{
node* temp = arr[i].head;
// if the queue was empty, arr[i].head->next
// dereferences a NULL pointer, which is
// undefined behaviour
arr[i].head = arr[i].head->next;
// This only removes one link from the queue.
// If there are more, you leak memory when you
// free arr below
free(temp);
}
free(arr);
}
如果是这样的话,您可能需要这样的东西:
void free_queues(queue *arr, int numberofsets)
{
for (size_t i = 0; i < numberofsets; i++) {
node* temp = arr[i].head, *next;
while (temp) {
next = temp->next;
free(temp);
temp = next;
}
}
free(arr);
}
您正在寻找数组的数组(我think/hope)。基本上,您想从一个“主”数组创建 n
全部可索引(这是一个词吗?)的队列。
所以你是这样看的:
idx
of
big
arry
_________________________________
|000| -----> [ one big queue ]
|001| -----> [ one big queue ]
|002| -----> [ one big queue ]
|003| -----> [ one big queue ]
|004| -----> [ one big queue ]
|...| -----> .................
|nth| -----> [ one big queue ]
_________________________________
#include <stdlib.h>
typedef struct node
{
unsigned long data;
struct node* next;
}
node;
typedef struct queue
{
int size;
int capacity;
node* head;
node* tail;
}
queue;
queue** build_queue(int num ,
int assoc
)
{
//here you create an array of arrays
//result is an array of pointers, each pointer going to a separate array
queue** result = malloc(num * sizeof(queue*));
int i;
for (i = 0; i < num; i++)
{
queue* q = malloc(sizeof(queue)); //memory for actual queue
result[i] = q;
q->head = NULL;
q->tail = NULL;
q->size = 0;
q->capacity = assoc;
}
return result;
}
void free_queues(int num_queues,
queue** qs
)
{
int i;
for (i = 0; i < num_queues; i++)
{
/*
* NOTE: you must use a while loop here to FIRST free the linked list qs[i]
* node* head = qs[i]->head;
* while(head != qs[i]->tail)
* {
* node* temp = head->next;
free(head);
head = temp;
* }
* free(qs[i]->tail);
*/
free(qs[i]); //frees the actual queue struct
}
free(qs); //frees the array of pointers to queues
}
int main(void)
{
int num = 5;
int assoc = 4;
queue** qs = build_queue(num, assoc);
free_queues(num, qs);
return 1;
}
最后用valgrind
检查是否有漏水。对于上述解决方案:
$ gcc please_work.c
$ valgrind ./a.out
==5974== Memcheck, a memory error detector
==5974== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==5974== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==5974== Command: ./a.out
==5974==
==5974==
==5974== HEAP SUMMARY:
==5974== in use at exit: 0 bytes in 0 blocks
==5974== total heap usage: 6 allocs, 6 frees, 160 bytes allocated
==5974==
==5974== All heap blocks were freed -- no leaks are possible
==5974==
==5974== For lists of detected and suppressed errors, rerun with: -s
==5974== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)