关于链表的第一个和最后一个元素的混淆

时间:2018-03-06 08:01:19

标签: c linked-list

我很困惑我们是否将元素添加到链接列表的前面或后面。我们假设我们有一个链接列表,如:x->a->c->v;这里,x是第一个还是最后一个元素?其次,如果我想添加x->a->c->v->hh->x->a->c->v,我该怎么办?当我遇到以下问题时,这让我很困惑:

  

考虑实施循环单链表数据结构。假设循环链表的指针ptr指向其link字段指向链表的第一个节点的最后一个节点。完成下面指定的add(...)delete(...)的算法。您可以使用伪代码或C代码编写。假设链表节点结构的以下声明:

typedef struct list_node* list_pointer;
typedef struct list_node {
     int value;
     list_pointer link;
}

list_pointer ptr = NULL;
     

请注意,如果循环链接列表为空,则其指针ptr将设置为NULL

// Add node at the front of the circular list ptr; ptr points at the last node in the list
void add(list_pointer *ptr, list_pointer node) { ... }

// Delete the front node from the list ptr
list_node delete(list_pointer *ptr) { ... }

3 个答案:

答案 0 :(得分:2)

第一个元素是x,因为如果你通过跟踪next指针链遍历列表,那么你将会得到第一个元素。

添加到链接列表时,可以在第一个元素之前添加,也可以在最后一个元素之后添加。在第一个元素之前添加更有效,因为您不必遵循整个next指针链来查找结尾。

答案 1 :(得分:2)

用于链接列表的常用术语是headtail

在非循环列表中,就像您在问题中显示的那样,head节点将是列表中没有其他节点指向的节点,因此您需要另一个指针,{{1指针,指向它。由于您通常遍历从listHead指向的节点开始的列表,因此listHead节点也可以被视为列表中的head节点。

在非循环列表中,first节点是不指向任何其他节点的节点。它可以被认为是列表中的tail节点。

现在,在循环列表中,与您链接的文字中引用的列表一样,lasthead以及tailfirst的定义可以是稍微复杂一点,因为每个节点都指向另一个节点并且有另一个节点指向它。循环列表的开始和结束通常由列表的排序顺序确定,如果有一个或其他一些遍历条件控制您通过列表的顺序。

基本循环列表可能包含last指针,该指针指向您在浏览列表时应访问的listHead节点。

一些更高级的循环列表将更改为使用first指针,指向列表的最后一个节点。这样做是因为使用循环列表,如果有指向listTail节点的指针,则很容易到达head节点,因为tail节点将指向{ {1}}节点。因此,通过提供指向tail节点的指针,您可以快速访问列表中的headtail节点。这是您的链接文本描述的数据结构类型。

现在有关插入的问题,这完全取决于您以及您希望如何使用该列表。如果列表是无序的,则将新节点作为列表的新last插入速度要快得多。但是,如果您想要实现先进先出列表,那么您可能希望将新节点作为列表的新first插入。当然,如果列表中有一个订单,根据每个节点包含的一些数据,那么您希望在列表中找到正确的位置以插入新节点以保留订购。

答案 2 :(得分:1)

您可以选择自己列表的方向。通常通过命名指向上一个和下一个节点的指针。如何命名它们决定了订单。如果你有一个双向链表,你的节点都有两个指针。

然而,您始终存储指向第一个和最后一个元素的指针。这样您就可以拥有push_frontpop_frontpush_backpop_back个功能。

但是,如果您有一个转发列表,(您只在节点中存储了next个指针,那么您就不能拥有pop_back,因为您的上一个节点没有链接到上一个节点,你不知道新的最后一个元素是什么。

所以

  • 转发列表可以包含:push_frontpop_frontpush_back
  • 后退列表可以包含:push_frontpush_backpop_back
  • 和双重链接列表:push_frontpop_frontpush_backpop_back