【问题标题】:Deque implementation based on doubly linked list not working基于双向链表的 Deque 实现不起作用
【发布时间】:2014-01-22 04:54:27
【问题描述】:

这是我使用双向链表实现双端队列的代码。它不工作..你能给我一些关于我哪里出错的指示吗?指针未初始化,代码卡在 addqatend 函数中。

#include <stdio.h>
#include <conio.h>
#include <iostream>
#include <string.h>
#include<time.h>
#include<math.h>
#include<ctype.h>
#include <malloc.h>
#include <Windows.h>

struct node
{
struct node *prev;
int data;
struct node *next;
};

struct queue
{
struct node *front;
struct node *rear;
};


void initqueue(struct queue *);
void addqatbeg(struct queue *,int);
void addqatend(struct queue *, int);
int delqatbeg(struct queue *);
int delqatend(struct queue *);
void delqueue(struct queue *);

int main()
{
struct queue a;
int i;

system("cls");
initqueue(&a);

addqatbeg(&a,11);
addqatbeg(&a,23);
addqatbeg(&a,-5);
addqatbeg(&a,45);

addqatend(&a,34);
addqatend(&a,78);

i = delqatbeg(&a);
if(i!=NULL)
    printf("item deleted from front:%d",i);
i = delqatbeg(&a);
if(i!=NULL)
    printf("item deleted from front:%d",i);
i = delqatend(&a);
if(i!=NULL)
    printf("item deleted from end:%d",i);
i = delqatend(&a);
if(i!=NULL)
    printf("item deleted from end:%d",i);

delqueue(&a);

system("pause");
return 0;
}

//initialise the queue
void initqueue(struct queue *q)
{
q->front = q->rear = NULL;
}

//add at the beginning of the queue
void addqatbeg(struct queue *q,int item)
{
struct node *temp;
temp = (struct node *)malloc(sizeof(struct node));
if(temp == NULL)
    printf("queue is full\n");
//temp->data = item;
//temp->link = NULL;
if(q->front == NULL)
{
    q->rear = q->front = temp;
    q->front->prev = NULL;
    q->front->next = NULL;
    q->rear->next = NULL;
    q->rear->prev = NULL;
    return;
}


q->front->data = item;
q->front->next = temp;
q->front = temp;
q->front->prev = q->front;
//q->rear->next = q->front->next;
//q->front->prev = q->rear;
}

//add at the end of the queue
void addqatend(struct queue *q, int item)
{
struct node *temp;
temp = (struct node*)malloc(sizeof(struct node));
if(temp == NULL)
    printf("queue is full\n");
if(q->front == NULL)
{
    q->rear = q->front = temp;
    q->front->prev = NULL;
    q->front->next = NULL;
    return;
}
while(q->front->next!=NULL)
    q->rear = q->front->next;
q->rear->data = item;
q->rear->next =temp;
q->rear = q->rear->next;
q->rear->prev = q->rear;
 }

//delete at the beginning of the queue
int delqatbeg(struct queue *q)
{
struct node *temp;
int item;
if(q->front ==NULL)
{
    printf("queue is empty:\n");
    return NULL;
}
item = q->front->data;
temp = q->front;
q->front = q->front->next;
free(temp);
return item;
 }

//delete at the end of the queue
 int delqatend(struct queue *q)
{
struct node *temp;
int item;
if(q->rear == NULL)
{
    printf("queue is empty\n");
    return NULL;
}
item = q->rear->data;
temp = q->rear;
q->rear = q->rear->prev;
free(temp);
return item;
}

//free the nodes
 void delqueue(struct queue *q)
{
struct node *temp;

if(q->front == NULL)
    return;
while(q->front!=NULL)
{
    temp = q->front;
    q->front = q->front->next;
    free(temp);
}
}

【问题讨论】:

  • 所以您希望我们梳理您的代码,理解它,找到您的错误,调试您的错误,并为您重新编码? “努力产生努力。”
  • 我是这里的新手..所以请你帮忙..我也是数据结构的新手
  • @jitendrakumar 您必须更具体地了解您所面临的确切问题。 “它不工作......”没有多大帮助。告诉我们哪个部分起作用以及它挂起或卡住的确切位置。
  • @AbhishekBansal,它卡在 while 循环中的第二个函数 addatend 中。它陷入了无限循环,并且指针 next、prev 和 data 似乎都未初始化。
  • @jitendrakumar 现在是学习如何调试代码的好时机。如果任何循环卡在 while 循环中,则表示未满足终止条件。如果您说指针未初始化,则回溯并检查代码的哪一部分按预期工作,最好使用调试器或至少通过将调试消息输出到控制台。

标签: c++ c pointers data-structures struct


【解决方案1】:

这里有各种各样的问题。

#include <stdio.h>
#include <conio.h>
#include <iostream>
#include <string.h>
#include<time.h>
#include<math.h>
#include<ctype.h>
#include <malloc.h>
#include <Windows.h>

呃,这是一大堆包含。您使用什么语言?下定决心。 &lt;iostream&gt; 是 C++ 头文件,其余的是 C 头文件。 &lt;malloc.c&gt; 是什么?通常,malloc 应该在&lt;stdlib.h&gt;&lt;windows.h&gt; 中。对于此示例,您只需要 &lt;stdlib.h&gt;&lt;stdio.h&gt;

如果我打开编译器警告,我会收到关于将整数比较和分配给指针的警告。在delqatend 中,您应该返回普通的0 作为错误代码,而不是NULL。同样在这里:

i = delqatbeg(&a);
if (i != NULL) 
    printf("item deleted from front:%d", i);

NULL应该是0。 (0 是空指针和空整数的语言表示,但宏 NULL 将其转换为 (void *),使其成为指针。这里的 i 是一个整数。)另外,请在字符串末尾打印一个换行符。

temp = (struct node *) malloc(sizeof(struct node));
if (temp == NULL)
    printf("queue is full\n");

如果您的作业内存不足,我喜欢队列已满,但您不应该只打印它,而应该做其他事情,例如中止进程或返回错误代码,否则您以后会做一些坏事函数指向NULL 指针。

好的,现在解决您的主要问题。让我们看看你的函数addqatbeg。在队列为空的情况下,您可以正确插入节点,尽管您实际上两次执行相同的分配,因为q-&gt;frontq-&gt;end 是相等的。但是您没有将数据分配给新节点。

另一种情况,队列中已经有一个节点,是一团糟。您不会通过在数据周围晃动来插入节点,而是通过指针重新组织队列结构。这是一个更好的addqatbeg

//add at the beginning of the queue
void addqatbeg(struct queue *q, int item)
{
    struct node *temp;

    // Create node and check for NULL
    temp = (struct node *) malloc(sizeof(struct node));

    if (temp == NULL) {
        printf("queue is full\n");
        return;
    }

    // Assign data
    temp->data = item;
    temp->prev = temp->next = NULL;

    // Insert node
    if (q->front == NULL) {
        q->rear = q->front = temp;
    } else {
        temp->next = q->front;
        q->front->prev = temp;
        q->front = temp;
    }
}

现在应该很容易实现addqatendaddqatendaddqatbeg 函数在您的情况下完全相似,因为您维护前向和后向指针。 addqatend 中的 while 循环是多余的,并引入了无限循环:您检查 q-&gt;front,但永远不要在循环中更新它。

【讨论】:

  • FWIW,您可以通过 (1) 始终设置 temp-&gt;next = q-&gt;front; before if-else 而不是将其初始化为 NULL 来减少添加。如果队列为空,q-&gt;front 无论如何都会为 NULL。然后(2)移动两个逻辑块的q-&gt;front = temp;重复行out,而不是always在if-else之后进行。 (和 +1 的答案,虽然如果你失去了 malloc() 结果的演员表,如果这应该是 C 代码)
  • 总有改进的余地。关于malloc 的演员表:代码本质上是C,所以应该删除。但考虑到 OP 包含&lt;iostream&gt;,我估计他会使用 C++ 编译器来编译它,这意味着可能需要演员表,因此决定将其保留。
【解决方案2】:

看看这些功能是否适合你。重复模式建议对常用函数进行一些重构,但请尝试一下。

添加qatbeg:

//add at the beginning of the queue
void addqatbeg(struct queue *q,int item)
{
struct node *temp;
temp = (struct node *)malloc(sizeof(struct node));
if(temp == NULL)
    printf("queue is full\n"); 

if(q->front == NULL)
{
    q->rear = q->front = temp;
    q->front->data = item;      
    return;
}
q->front->next = temp;
q->front = q->front->next;
q->front->data = item;    
}

添加qatend:

//add at the end of the queue
void addqatend(struct queue *q, int item)
{
struct node *temp;
temp = (struct node *)malloc(sizeof(struct node));
if(temp == NULL)
    printf("queue is full\n"); 

if(q->rear == NULL)
{
    q->rear = q->front = temp;
    q->rear->data = item;  
    return;
}
q->rear->prev = temp;    
q->rear = q->rear->prev;
q->rear->data = item;    
}

德尔卡特贝格:

//delete at the beginning of the queue
int delqatbeg(struct queue *q)
{
struct node *temp;
int item;

if(q->front == NULL)
{
    printf("queue is empty:\n");
    return NULL;
}

item = q->front->data;
    temp = q->front;
    q->front = q->front->prev;        
    free(temp);
}    
return item;
}

Delqatend:

//delete at the beginning of the queue
int delqatend(struct queue *q)
{
struct node *temp;
int item;

if(q->rear == NULL)
{
    printf("queue is empty:\n");
    return NULL;
}

    item = q->rear->data;
    temp = q->rear;
    q->rear = q->rear->next;        
    free(temp);
return item;
}

【讨论】:

  • 你真的编译过代码吗?有编译器警告?然后查了? (提示:它不能编译,delqatbeg 中有一个流浪的 }。提示 II:有编译器警告关于 int 和指针之间的不一致。提示 III:它没有按预期工作。)在考虑重构之前你应该试着让你的代码正确。在所有插入和删除之后,双端队列中的frontrearnextprev 指针必须保持一致。
  • 我阅读了他的代码并在帖子中重写了它。将遵循您的提示。
猜你喜欢
  • 2019-08-16
  • 2021-11-18
  • 2011-06-03
  • 2018-03-14
  • 2012-05-10
  • 2013-02-22
  • 2017-06-10
  • 1970-01-01
相关资源
最近更新 更多