当前位置: 首页 > 知识库问答 >
问题:

单链表尾巴

司寇高洁
2023-03-14

如果你想创建一个像这样的单链表:

struct Node { 
    int data;
    Node *next;
};

struct List{ 
    Node *head;
    // Node *tail; --> necessary?
    Node *last;
};

这个列表有方法“追加”、“删除”、“printList”和“findElement”。有必要有尾巴吗?因为使用“最后”你可以地址最后一个节点。

那么,什么时候有必要拥有所有三个节点“头”、“尾”和“最后”?例如,当您想将排序的节点插入列表时?

共有3个答案

赫连靖琪
2023-03-14

我认为这取决于你想使用什么操作。

>

  • 假设您希望插入和删除列表末尾的节点,那么在列表中保留最后一个节点肯定是明智的选择。

    否则,如果要在列表开头执行操作,则不需要最后一个节点。

  • 锺离飞尘
    2023-03-14

    实际上,您可以实现排队(在尾部追加)、推(在头部前置)、出列(从头部移除),当然还可以使用一个指针头查找和打印。诀窍是使列表循环并使标题指向尾部。然后tail-

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct node_s {
      struct node_s *next;
      int data;
    } Node;
    
    typedef struct list_s {
      Node *tail;
    } List;
    
    Node *new_node(int data) {
      Node *node = malloc(sizeof *node);
      node->data = data;
      node->next = node;
      return node;
    }
    
    void init_list(List *list) {
      list->tail = NULL;
    }
    
    int is_empty(List *list) {
      return list->tail == NULL;
    }
    
    void enqueue(List *list, Node *node) {
      if (list->tail) {
        Node *head = list->tail->next;
        node->next = head;
        list->tail->next = node;
        list->tail = node;
      } else list->tail = node->next = node;
    }
    
    void push(List *list, Node *node) {
      if (list->tail) {
        Node *head = list->tail->next;
        node->next = head;
        list->tail->next = node;
      } else list->tail = node->next = node;
    }
    
    Node *dequeue(List *list) {
      Node *head = list->tail->next;
      if (head == list->tail)
        list->tail = NULL;
      else
        list->tail->next = head->next;
      return head;
    }
    
    void print_list(List *list) {
      printf("The list:\n");
      if (list->tail) {
        Node *head = list->tail->next;
        Node *p = head;
        do {
          printf("%d\n", p->data);
          p = p->next;
        } while (p != head);
      }
    }
    
    int main(int argc, char *argv[]) {
      List list[1];
      init_list(list);
    
      // Build the list in order and print it.
      for (int i = 0; i < 4; i++) enqueue(list, new_node(i));
      print_list(list);
    
      // Remove elements from head until empty.
      printf("Dequeueing:\n");
      while (!is_empty(list)) {
        Node *node = dequeue(list);
        printf("%d\n", node->data);
        free(node);
      }
    
      // Build the list in reverse order and print it.
      for (int i = 0; i < 4; i++) push(list, new_node(i));
      print_list(list);
    
      return 0;
    }
    

    曾绯辞
    2023-03-14

    不,没有必要。尾部等于头部-

    还要注意,字段last有点不寻常。在大多数用例中,您将元素添加到单链表的头部,并在真正需要添加到末尾时使用不同的数据结构。

     类似资料:
    • 我已经在这上面困了半天了。我可以得到一些提示或指针,如何交换一个链表的头部和尾部(而不是反转整个列表),而不复制他们的数据吗? 如果我能看到代码并对它有一个解释,那就太棒了! 编辑: null 通过列表查找列表的第二个最后节点,并将其链接到头部。 将原来的头部链接到null,就像现在一样,头部应该被交换到尾部。

    • 我正在尝试为我的链表类创建一个添加和删除方法。我写了两封信,名字是Head和Tail。 头- 当我试图删除特定节点时,我一直遇到问题,因为Java说我越界了。我想是因为我的头没有指向第一个节点?你们觉得怎么样?还是我完全走错路了...

    • [采访问题] 编写一个函数,该函数将在一次传递中从单个链表整数的尾部(或尾部)返回第5个元素,然后提供一组针对该函数的测试用例。 这类似于问题:如何从单链表的末尾找到第n个元素?,但是我还有一个额外的要求,我们应该只遍历链接列表一次。 这是我的解决方案: 我只遍历链表一次,并使用隐式递归堆栈。另一种方法是有两个指针:快指针和慢指针,快指针是比慢指针快的k个指针。哪一个看起来更好?我认为有两个指针的

    • 似乎人们总是说,如果一个单链接列表的头是空的,那么这个列表是空的,但是检查尾部也会起作用吗?假设我确实知道一个列表有一个尾部,我可以检查尾部是否为空以确定它是否为空吗?

    • 问题内容: 我需要用Java编写一个将链表中的第一个元素移动到最后位置的方法。 为此,我相信我必须设置一个节点以引用head之后的第一个元素,然后将下一个节点设置为null。我尝试使用我的方法执行此操作,但是在运行该方法时,输出不正确。 我所剩的班级太多了,无法在此处发布,但是我认为我只需要在概念化如何将第一个元素移到列表末尾方面提供帮助。 我写的方法是: 问题答案: 您要删除列表的开头并使其成为

    • 我第一次使用链表,必须创建一个可以在双链表末尾插入节点的函数。到目前为止我 Node类按顺序接受要存储的值、要指向的下一个指针的值和上一个指针的值。每当我试图在这里插入节点时,我都会得到一个错误,说有一个未处理的异常,并且在写入位置0x00000008时有访问冲突。 我不完全确定这里出了什么问题,但我认为这与根据错误消息取消引用空指针有关。我真的很感激有人帮忙解决这个问题。