我想使用链表创建一个循环队列,我也希望创建该数据结构(队列)的实例而不仅仅是一个队列,多个队列而不重复代码。这就是我想出来的......
#include <stdio.h>
#include <stdlib.h>
struct queue
{
int info;
struct queue *next;
struct queue *front;
struct queue *rear;
};
void create(struct queue **q)
{
(*q)->next = 0;
(*q)->front = 0;
(*q)->rear = 0;
}
struct queue* makenode(int item){
struct queue* p = (struct queue*)malloc(sizeof (struct queue));
if (p) p->info = item;
return p;
}
void addLast(struct queue **q, int item){
struct queue* p = makenode(item);
if ((*q)->front == NULL){
(*q)->front = (*q)->rear = p;
(*q)->front->next = (*q)->front;
(*q)->rear->next = (*q)->rear;
}
else
{
(*q)->rear->next = p;
p->next = (*q)->front;
(*q)->rear = p;
}
}
int delFirst(struct queue **q){
struct queue *p = (*q)->front;
if ((*q)->front == 0)
printf("\nEmpty Queue\n");
else
{
int temp = (*q)->front->info;
if (((*q)->front->next) != ((*q)->front))
{
(*q)->front = (*q)->front->next;
(*q)->rear->next = (*q)->front;
}
else
{
(*q)->front = 0;
}
return temp;
}
free(p);
}
void main()
{
struct queue *premium, *normal;
create(&premium);
create(&normal);
addLast(&premium, 5);
addLast(&premium, 10);
addLast(&normal, 20);
addLast(&normal, 30);
printf("%i\n", delFirst(&premium));
printf("%i\n", delFirst(&premium));
delFirst(&premium);
printf("%i\n", delFirst(&normal));
printf("%i\n", delFirst(&normal));
delFirst(&normal);
getch();
}
有什么好办法吗?我觉得我的代码很复杂。我是C编程的新手,我只学习了关于队列和链表的基础知识。所以我甚至不知道我的代码是100%正确还是优雅的代码。我使用DevC ++编译此代码工作正常,但是当我使用MS Visual Studio 2013编译它时,它给了我一个例外“访问违规写入位置....”所以我非常确定我的代码不是那么好。请帮助我出去了。谢谢
答案 0 :(得分:3)
问题1:数据结构
你有一个结构,包含链表项(信息和下一个元素)和队列结构(前面和后面,对于所有元素应该是相同的。
我建议使用:
struct queue_item
{
int info;
struct queue_item *next;
};
struct queue
{
struct queue_item *front;
struct queue_item *rear;
};
问题2:队列创建
当您致电create()
时,您传递的地址指针(例如premium
)尚未初始化。它可以指向任何地方!肯定是无效的位置。它还没有指向队列。因此,当您执行(*q)->next = 0;
之类的操作时,您会尝试覆盖非法位置。
根据上面提出的数据结构,我提出以下建议:
struct queue* create (struct queue *q) /* q points to a queue already allocated, or it is NULL */
{
if (q==NULL)
q = malloc(sizeof (struct queue));
if (q) {
q->front = 0;
q->rear = 0;
}
return q;
}
在main()
中,您可以选择:
struct queue *premium, normal;
premium = create(NULL); /* allocate the queue structure */
create(&normal); /* use an allocated structure */
问题3:节点指针未在节点创建时初始化
malloc()
不会初始化它返回的内存。如果你没有初始化链接指针,那么这些指针实际上可能包含NULL
之外的其他内容。
struct queue_item* makenode(int item){
struct queue* p = (struct queue_item*)malloc(sizeof (struct queue_item));
if (p) {
p->info = item;
p->next = NULL; /* There is no link yet, so make it clear to avoid any surprises later. */
}
return p;
}
问题4:添加/删除项目时出现不一致
使用新的数据结构,您必须调整addLast()
和delFirst()
。但它会更清晰,因为front
和rear
位于队列级别,next
仅位于项目级别。
从签名中,可以避免双重间接,因为这些操作永远不会改变指向队列的指针:
void addLast(struct queue *q, int item);
int delFirst(struct queue *q);
答案 1 :(得分:1)
您的第一个问题是您在未初始化的指针上调用create()
:
void create(struct queue **q)
{
(*q)->next = 0;
…
}
int main()
{
struct queue *premium, *normal;
create(&premium);
create(&normal);
您需要在makenode()
函数或create()
内调用main()
,或者您需要提供premium
和normal
的结构以指向
选项A:
void create(struct queue **q)
{
*q = makenode(0);
if (*q != 0)
{
(*q)->next = 0;
…
}
}
选项B:
int main()
{
struct queue q_premium, q_normal;
struct queue *premium = &q_premium;
struct queue *normal = &q_normal;
create(&premium);
create(&normal);
任何一种技术都可以使用,但是选项B需要小心,因为结构q_premium
和q_normal
没有被分配(尽管它们可能是必要的)。但是,create()
的签名表明选项A是预期的,因为选项B确实不需要create()
中的双指针。
我不清楚,如果有的话,三个指针 - front
,rear
,next
的组合会对你的结构有所帮助。为了自己的利益,我实现了一个循环DLL,只是为了看看可能涉及的内容,我只需要一个数据指针以及下一个和前一个指针。从列表中的任何元素,您都可以访问列表中的每个其他元素。您可以在给定节点之前或之后插入,删除给定节点,将函数应用于所有节点,或查找与函数提供的谓词匹配的第一个节点(并获取下一个节点,上一个节点或数据),或者销毁整个清单。
我的印象是,如果没有指针,您的代码会更简单。
随着选项A的变化,代码编译并且似乎有效,产生:
5
10
Empty Queue
20
30
Empty Queue