在链表中排队功能

时间:2016-09-04 14:17:27

标签: c pointers linked-list singly-linked-list

我正在努力理解我的教授所做的“入队”功能,但我没有采取任何措施。

struct queue_node {
int item;
struct queue_node* next;
};
typedef struct queue_node* queue;


int enqueue (queue* tail, int i) {
queue n;
queue *iter;
n = (queue)malloc(sizeof(struct queue_node));
if (!n) return 1;
n->item = i;
n->next = NULL;
for (iter=tail; *iter != NULL; iter = &((*iter)->next)
;
*iter = n;
return 0;
}

首先是“typedef struct queue_node * queue;”令我困惑,所以我试图以这种方式重新解释代码(如果我错了,请更正代码)

struct queue_node {
int item;
struct queue_node* next;
};
typedef struct queue_node queue;

int enqueue (queue **tail, int i) {
queue *n;
queue **iter;
n = (queue)malloc(sizeof(struct queue_node));
if (!n) return 1; --->what does that mean?
n->item = i;
n->next = NULL;
for (iter=tail; **iter != NULL; iter = &((*iter)->next)--->last part of the for is unclear to me... can i rewrite it as "iter = **((iter)->next)"?
;
*iter = n; -->this is the part i don't really get...
return 0;
}

顺便说一句,在尝试阅读我的教授的解决方案之前,我试图在我自己的身上做一个“入队”功能

typedef struct node{
int value;
struct node *next;
}node;

void enqueue(node *head,int data){
if(head->next != NULL){
enqueue(head->next,data);
}
node *new=NULL;
new=malloc(sizeof(node));
new->value=data;
new->next=NULL;
head->next=new;
}
这是好事吗?或者我不能用它?提前感谢大家的帮助

3 个答案:

答案 0 :(得分:2)

如果要使用queue

的定义
struct queue_node 
{
    int item;
    struct queue_node *next;
};

typedef struct queue_node queue;

然后该功能将按以下方式显示。

int enqueue( queue **tail, int item ) 
{
    queue *node = ( queue * )malloc( sizeof( queue ) );
    int success = node != NULL;

    if ( success )
    {
        node->item = item;
        node->next = NULL;

        while ( *tail != NULL ) tail = &( *tail )->next;

        *tail = node;
    }

    return success;
}

与函数定义相反,此函数在成功时返回1,即成功分配将附加到队列的新节点,否则返回0。

因此,如果您按以下方式声明了队列

queue * head = NULL;

然后函数调用看起来像

enqueue( &head, value );

其中value是一个整数表达式。

如您所见,您需要使用指针间接传递queue的头部。否则,如果不使用指针并将头部直接传递给函数,则函数将获得头部的副本。因此,函数中副本的任何更改都不会影响原始头部。

在本声明中

    queue *node = ( queue * )malloc( sizeof( queue ) );

创建一个新节点。函数malloc返回指向已分配动态节点的指针。

在本声明中

    int success = node != NULL;

根据node != NULL的调用是否成功,分配了表达式malloc(1或0)的结果。

如果malloc的调用成功node不等于NULL,则初始化新节点并将其附加到队列的末尾。         如果(成功)         {             node-> item = item;             node-> next = NULL;

        while ( *tail != NULL ) tail = &( *tail )->next;

        *tail = node;
    }

如何找到列表的尾部?

如果列表最初为空,则*tail等于NULL,并且while *tail != NULL上的条件将等于false。因此,等于tail的{​​{1}}的当前值将替换为已分配节点的地址

NULL

如果*tail = node; 不等于*tail,我们会获得当前节点的数据字段NULL

next

反过来取其地址的方式与我们通过引用

将头部传递给函数的方式相同
( *tail )->next

最后,当此数据字段包含NULL时,我们将此&( *tail )->next 替换为新创建节点的地址。

如果你想编写一个将新节点附加到队列的递归函数,那么它可能看起来像

NULL

答案 1 :(得分:2)

你和你的教授基本上以不同的方式处理变量。根据当时的命名,我认为教授的目标是看起来像这样的图片: enter image description here

tail指针指的是你要从哪个最右边的节点出队,并且到达你入队的位置,你会迭代直到你到达队列的前面。现在需要注意的重要一点是,iter并不直接指向节点,它指向每个节点中的next个单元格,直到它找到NULL个单元格为止,我试图说明这里。

enter image description here

我认为在实践中你是对的,不想只是为了添加节点而遍历队列。实际的队列实现(有时使用链接列表)需要恒定时间O(1)入队和出队,因此它们始终保持指向队列任一端的指针。

最后,每个人对C命名约定都有不同的看法,但我倾向于同意你的看法,教授的例子有一些令人困惑的typedef。像linux内核这样的代码库建议不要使用typedef来指示甚至结构。

答案 2 :(得分:0)

typedef struct queue_node* queue;定义了一个新类型,以便您可以编写

queue* myqueue = (queue*)malloc(sizeof(struct queue_node));

而不是

struct queue_node** myqueue = (struct queue_node**)malloc(sizeof(struct queue_node));

正如评论中所指出的,这是一种指向指针的类型。

该行

if (!n) return 1;

测试指针n是否有效(即不是NULL),如果比较失败,则返回1作为错误代码。

现在代码

for (iter=tail; **iter != NULL; iter = &((*iter)->next)
{
    *iter = n; /* -->this is the part i don't really get... */
    return 0;
}

遍历列表,直到遇到NULL指针。 行*iter = n;取消引用当前迭代器(在这种情况下是指向当前node的指针并为其分配n。所以这实际上是搜索队列的末尾并分配新的元素到底。

**((iter)->next) 

不同
&((*iter)->next)

语句(*iter)->next解除引用iter,它是指向struct queue_node的指针,因此您只有指向queue的实际指针。然后它从next获取queue字段。 &为您提供了指向next引用的元素的指针(它是地址运算符),而您的代码将为您提供->next引用的实际对象。 / p>

现在你的代码是:

void enqueue(node *head,int data)
{
    if(head->next != NULL) /* what happens if head is  NULL ?*/
    {
         enqueue(head->next,data);
    }
    node *new=NULL;
    new=malloc(sizeof(node));
    new->value=data;
    new->next=NULL;
    head->next=new;
}

除了我在开头的评论,我看不出它有什么问题。但我实际上没有测试代码是否运行;)

我希望这会让事情更加清晰。 :)如果我的解释有任何含糊之处,请发表评论,不要简单地投票,我知道我不是最有经验的C程序员。