当前位置:   article > 正文

带你详细了解链表_链表有哪些

链表有哪些


一、什么是链表?

链表(Linked List)是一种常见的数据结构,它由节点(Node)组成,每个节点包含两部分:数据域(存储元素值)和指针域(指向下一个节点)。链表使用指针来连接各个节点,形成一个逻辑上的序列。

常见的链表类型有单向链表、双向链表和循环链表。

  1. 单向链表(Singly Linked List):每个节点只包含一个指针,指向下一个节点。最后一个节点指向 null,表示链表的结束。

  2. 双向链表(Doubly Linked List):每个节点包含两个指针,分别指向前一个节点和后一个节点。首节点的前置指针和尾节点的后置指针都指向 null。

  3. 循环链表(Circular Linked List):在单向链表或双向链表的基础上,将尾节点的指针指向首节点(或将首节点的前置指针指向尾节点),形成一个环形结构。

二、链表的实现

1.链表的方法

首先我们将所有的方法放在一个接口里。

将链表的常见操作放在接口中,可以方便类的实现对这些操作进行统一的定义和实现。这样做的好处就是可以在不同的类中使用相同的方法名,而无需考虑具体实现细节。接口定义了一组行为规范,同一个接口的多个实现类可以共用该接口提供的方法,从而实现代码的复用和扩展。对于链表这种数据结构,许多常见的操作都是固定的,将其定义在接口中可以让其他类更容易地调用和重用这些方法。此外,将链表的常见操作封装在接口中,可以使代码更加抽象化,并隐藏底层实现细节。这有助于提高代码的可读性、可维护性和可扩展性,同时也可以使代码更加安全,减少出错的可能性。

同时我们创建一个链表。

1.1头插法

void addFirst (int data);

  1. @Override
  2. public void addFirst(int data) {
  3. ListNode node = new ListNode(data);
  4. if(head == null){
  5. this.head = node;
  6. }else {
  7. node.next = head;
  8. this.head = node;
  9. }
  10. }

  1. 创建一个新节点 ListNode,并将其数据域设置为 data。
  2. 检查链表是否为空(即 head 是否为 null)。如果链表为空,说明此时新节点就是链表中唯一的节点,将 head 指向新节点即可。
  3. 如果链表不为空,将新节点的 next 指针指向原来的头节点,然后将 head 指向新节点。这样就实现了在链表头部插入新节点的操作。

1.2尾插法

void addLast(int data);

  1. @Override
  2. public void addLast(int data) {
  3. ListNode node = new ListNode(data);
  4. ListNode cur = this.head;
  5. if (head == null){
  6. this.head = node;
  7. }else{
  8. while (cur.next != null){
  9. cur = cur.next;
  10. }
  11. cur.next = node;
  12. }
  13. }
  1. 创建一个新节点 ListNode,并将其数据域设置为 data。
  2. 声明一个指针 cur,初始化为头节点 head。
  3. 检查链表是否为空(即 head 是否为 null)。如果链表为空,说明此时新节点就是链表中唯一的节点,将 head 指向新节点即可。
  4. 如果链表不为空,通过循环找到链表的最后一个节点,即 cur.next 为 null 的节点。
  5. 将最后一个节点的 next 指针指向新节点,即将新节点插入到链表的尾部。

1.3任意位置插入,第一个数据节点为0号下标

void addIndex(int index,int data);

  1. @Override
  2. public void addIndex(int index, int data) {
  3. if (index < 0 || index > size()) {
  4. return;
  5. }
  6. if (index == 0) {
  7. addFirst(data);
  8. return;
  9. }
  10. if (index == size()) {
  11. addLast(data);
  12. return;
  13. }
  14. ListNode cur = searchPrev(index);
  15. ListNode node = new ListNode(data);
  16. node.next = cur.next;
  17. cur.next = node;
  18. }

1.4查找是否包含关键字为key的节点

boolean contains(int key);

  1. public ListNode FindKthToTail(int k){
  2. if(k <= 0 || head ==null){
  3. return null;
  4. }
  5. ListNode fast = head;
  6. ListNode slow = head;
  7. int count = 0;
  8. while (k-1 !=count) {
  9. fast = fast.next;
  10. //处理k太大的问题
  11. if(fast == null){
  12. return null;
  13. }
  14. count++;
  15. }
  16. while (fast.next != null){
  17. fast = fast.next;
  18. slow = slow.next;
  19. }
  20. return slow;
  21. }

  1. 首先,检查输入的 k 是否小于等于 0 或者链表 head 是否为 null。如果满足其中任一条件,说明无法找到倒数第 k 个节点,返回 null。

  2. 初始化两个指针 fast 和 slow,均指向头节点 head。使用一个计数器 count 来记录当前遍历到的节点位置,初始值为 0。

  3. 在 while 循环中,当 count 不等于 k-1 时,将 fast 指针向后移动一位,并递增 count 的值。这样做的目的是为了使 fast 指针领先 slow 指针 k-1 个节点。

  4. 在移动 fast 指针时,需要处理 k 大于链表长度的情况。即当 fast 指针移动到末尾时(fast == null),说明 k 太大,无法找到倒数第 k 个节点,返回 null。

  5. 当 fast 指针移动到末尾时,slow 指针所指的节点即为倒数第 k 个节点。

  6. 最后,返回 slow 指针所指的节点作为结果。

1.5删除第一次出现关键字为key的节点

void remove(int key);

  1. @Override
  2. public void remove(int key) {
  3. if(this.head == null){
  4. return;
  5. }
  6. if(this.head.val == key){
  7. this.head = this.head.next;
  8. return;
  9. }
  10. ListNode cur = findPrev(key);
  11. if(cur == null){
  12. System.out.println("没有你要删除的数字");
  13. return;
  14. }
  15. ListNode del = cur.next;
  16. cur.next = del.next;
  17. }
  18. private ListNode findPrev(int key){
  19. ListNode cur = this.head;
  20. while (cur.next != null){
  21. if(cur.next.val == key){
  22. return cur;
  23. }
  24. cur = cur.next;
  25. }
  26. return null;
  27. }
  1. 首先,检查头节点 head 是否为 null。如果链表为空,则直接返回。

  2. 检查头节点的值是否等于要删除的值 key。如果相等,说明要删除的节点就是头节点,将头节点的下一个节点作为新的头节点即可,然后返回。

  3. 如果头节点不是要删除的节点,需要找到要删除节点的前一个节点 cur。调用 findPrev 方法来寻找对应值为 key 的节点的前一个节点。

  4. 当 cur 为 null 时,说明找不到要删除的值 key,输出提示信息并返回。

  5. 如果能找到要删除的节点的前一个节点 cur,将要删除的节点 del 设置为 cur 的下一个节点 cur.next。

  6. 将 cur 的 next 指针指向 del 的下一个节点 del.next,从而跳过 del 节点,实现删除操作。

1.6打印

void display();

  1. @Override
  2. public void display() {
  3. ListNode cur = this.head;
  4. while (cur != null){
  5. System.out.print(cur.val+" ");
  6. cur = cur.next;
  7. }
  8. }


总结

以上就是今天要讲的内容,有什么不对的地方欢迎大家指正。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号