暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

数据结构——链表

IT的世界 2024-05-19
33

在学习链表之前,现在解决在数据结构——数组的学习最后给出的简单的算法题:
    
    leetcode,1. 找出可整除性得分最大的整数:
    
    给你两个下标从 0 开始的整数数组 nums 和 divisors 。
    divisors[i] 的 可整除性得分 等于满足 nums[j] 能被 divisors[i] 整除的下标 j 的数量。
    返回 可整除性得分 最大的整数 divisors[i] 。如果有多个整数具有最大得分,则返回数值最小的一个。
    

     public int maxDivScore(int[] nums, int[] divisors) {
    //cut 记录中间结果,用于更新最大得分
    //ans 最终结果,并当得分相同时,取数值小的返回
    int cnt = -1, ans = 0;

    //依次遍历divisor,计算其可整除得分
    for (int i = 0; i < divisors.length; i++) {
    int tmp = 0;
    for(int j = 0; j < nums.length; j++) {
    if (nums[j] % divisors[i] == 0) {
    tmp++;
    }
    }

    //更新最大得分和返回值
    if (tmp > cnt || (tmp == cnt && divisors[i] < ans)) {
    cnt = tmp;
    ans = divisors[i];
    }
    }
    return ans;
    }


    链表的概念

    上图显示的就是一个简单的链表。链表是由一系列节点组成的数据结构,其中每个节点都包含数据和指向下一个节点的引用。每个节点都连接着下一个节点,形成了一种线性序列。与数组不同,链表中的节点在内存中可以存储在不连续的位置,因此链表具有更灵活的内存使用方式。

    从链表的概念中,我们可以发现其特点:
    1. 由一系列节点组成,节点分成数据和指针两部分
    2. 链表在内存中的存储不连续
    3. 链表也是一种线性序列

    学习链表,通常会将它与数组进行比较:

    通过上面的表格,数组与链表的异同一目了然,根据不同的特点,选择不同的数据结构。

    链表的实现

    链表的实现通常包括两个类:节点类和链表类。节点类表示链表中的每个节点,包含一个数据字段和一个指向下一个节点的指针。链表类则负责管理节点之间的连接关系。

    让我们看一下简单的链表的实现(Java代码):

      //定义链表节点的结构
      class ListNode {
      int val; // 数据
      ListNode next; //指针
      ListNode(int val) {
      this.val = val;
      }
      }


      //定义链表类
      public class LinkedList {
      private ListNode head;


      public LinkedList() {
      this.head = null;
      }


      // 插入节点到链表尾部
      public void insert(int val) {
      ListNode newNode = new ListNode(val);
      if (head == null) {
      head = newNode;
      } else {
      ListNode curr = head;
      while (curr.next != null) {
      curr = curr.next;
      }
      curr.next = newNode;
      }
      }


      //根据index,查询指定的节点并返回
      public ListNode getNodeAtIndex(ListNode head, int index) {
      if (head == null || index < 0){
      return null;
      }
      ListNode current = head;
      int count = 0;


      while (current != null) {
      if (count == index)
      return current;
      count++;
      current = current.next;
      }


      return null; // 如果链表长度小于index,返回null
      }


      // 遍历链表并打印节点值
      public void display() {
      ListNode curr = head;
      while (curr != null) {
      System.out.print(curr.val + " ");
      curr = curr.next;
      }
      System.out.println();
      }
      }


      着重学习下链表的插入和删除操作:
          要在链表中插入节点,首先需要找到要插入位置的前一个节点,然后将新节点插入到其后面。如图:

         //指定位置,插入指定的节点
        public void insertNode(ListNode head, int position, int value) {
        if (head == null || position < 0)
        return;


        ListNode newNode = new ListNode(value);


        if (position == 0) {
        newNode.next = head;
        head = newNode;
        return;
        }


        ListNode prev = null;
        ListNode current = head;
        int count = 0;


        while (current != null && count < position) {
        prev = current;
        current = current.next;
        count++;
        }


        if (count == position) {
        prev.next = newNode;
        newNode.next = current;
        } else {
        System.out.println("Position out of bounds");
        }
        }

        当你删除链表中的一个节点时,你需要更新前一个节点的 next 指针,使其跳过被删除的节点,指向被删除节点的下一个节点。这样就可以将被删除节点从链表中移除。如图:

          //删除指定的节点
          public ListNode deleteNode(ListNode head, int position) {
          if (head == null || position < 0)
          return head;


          if (position == 0)
          return head.next;


          ListNode prev = null;
          ListNode current = head;
          int count = 0;


          while (current != null && count < position) {
          prev = current;
          current = current.next;
          count++;
          }


          if (count == position && current != null) {
          prev.next = current.next;
          }


          return head;
          }


           链表的应用

          链表在实际中有广泛的应用,包括但不限于以下几个领域:

          - 大名鼎鼎的区块链的实现
          - 数据结构:栈、队列、图等数据结构可以使用链表来实现。
          - 内存管理:动态内存分配和释放时,链表可以帮助管理内存的分配情况。
          - 文件操作:链表可以用于处理大型文件的读取和写入操作,以及记录文件系统中的目录结构等。
          等等。。。

          至此,我们已经知道的简单的单链表的基本概念与操作。没错,链表还有更多复杂的分类:双向链表,循环链表,是否带头结点也是重要的一种情形。如下图所示:

          其实弄懂了单链表的操作,其他链表的操作基本类似。对于链表的操作,只需要牢记所要操作的节点的当前指针,和前后节点的指针的位置关系,不遗漏,不错指。

          小试牛刀

          最后附上一道简单的算法题,巩固今天所学:
              leetcode , LCR 024. 反转链表
              给定单链表的头节点 head ,请反转链表,并返回反转后的链表的头节点。

          文章转载自IT的世界,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

          评论