链表(Linked list)是一种常用的数据结构,它由一系列节点组成,每个节点包含数据域指针域。指针域存储了下一个节点的地址,从而建立起各节点之间的线性关系。

1、链表节点

1.1 节点构成链表节点如下图所示:


其中,数据域可以是一个int、string、float或者数组等复杂结构。

1.2 节点表示

1.2.1 Golang语言

Go语言中的数据类型可以分为四大类:基础类型、聚合类型、引用类型和接口类型。

基础类型是构成编程语言的基础元素,包括整数、浮点数、布尔值和字符串等。在Go语言中,整型分为有符号和无符号整数,例如int8、int16、int32、int64等。此外,Go语言还支持基于架构的类型,例如uintptr。

聚合类型是由基础类型构成的复合数据类型,主要包括数组和结构体两种。数组由一组相同类型的元素组成,长度固定;结构体则由一组不同类型的元素(字段)组成,长度也是固定的。

引用类型是对底层数据进行抽象表示的类型,包括指针、切片、映射(也称为map)、函数和通道(channel)。指针提供了对底层变量的间接访问方式,切片是对数组的抽象,映射是一种关联数组,函数和通道则是特殊的引用类型,用于表示执行代码和传输数据。

接口类型是Go语言中的一种特殊类型,它定义了一组方法(函数),但是这些方法不包含(实现)代码。任何其他类型只要实现了这些方法就可以被看作是这个接口类型的实例。

因此,对于 Golang语言来说,只有结构体才可以表示链表的节点。

// ListNode 定义链表节点
type ListNode struct {
    Val  int       //链表的数据域
    Next *ListNode //链表的指针域
}

1.2.2 Java语言

基本数据类型:包括整型(byte、short、int、long)、浮点型(float、double)、字符型(char)和布尔型(boolean)。

引用数据类型:包括类(class)、接口(interface)、数组(array)和枚举(enum)。

特殊数据类型:包括void、String、Object等。

因此,对于 Java语言来说,只有类(class)才可以表示链表的节点。

 //定义链表节点
    static class ListNode {
        private int val;  //链表的数据域
        private ListNode next; //链表的指针域

        public ListNode(int val) {
            this.val = val;
            this.next = null;
        }

    }

1.2.3 Python语言

Python语言中有几种主要的数据类型,包括:
数字:Python可以处理整数(int)、浮点数(float)、复数(complex)。
字符串:字符串是Python中的文本数据类型,由零个或多个字符组成。
布尔值:布尔值是Python中的逻辑数据类型,有两个可能的值:True和False。
列表:列表是Python中的有序集合,可以包含任意类型的数据项。
元组:元组与列表类似,是有序的集合,但是元组是不可变的,这意味着你不能更改元组中的元素。
集合:集合是无序的、不重复的元素序列。
字典:字典是无序的键值对集合,键是唯一的。
None:None是一个特殊的类型,表示空或没有值。
自定义类和对象:Python允许用户定义自己的数据类型,即类。对象是类的实例。

因此,对于 Python语言来说,只有自定义类才可以表示链表的节点。

#定义链表节点
class ListNode:
    def __init__(self, data):
        self.val = data  # 链表的数据域
        self.next = None  # 链表的指针域

2、新建链表

创建链表代码实例如下:

  • go代码:

    head := &ListNode{Val: 1}
  • java代码

    ListNode head = new ListNode(1);
  • Python代码

    head = ListNode(1)

生成的链表结构如下图所示:

创建了一个链表,该链表只有一个节点,数据域的值为1,指针域指默认指向为Null。创建的链表只有一个节点,通过变量head指向它,后续就可以通过head变量来操作此链表了。

3、链表添加节点

原链表结构如下图所示:

给链表添加一个节点的代码实例如下:

  • go代码:

    head.Next = &ListNode{Val: 123} //更改原链表节点的指针域,让它指向一个新的节点
  • java代码

    head.next = new ListNode(123); //更改原链表节点的指针域,让它指向一个新的节点
  • Python代码

    head.next = ListNode(123)  # //更改原链表节点的指针域,让它指向一个新的节点

添加节点之后,链表结构如下所示:

原链表节点head的指针域next从指向Null改为指向123这个节点了。

如果要在链表默认增加2个节点,可以这样操作:

  • go代码:

    head.Next.Next = &ListNode{Val: 456} //给head 指针变量指向节点的 下下节点 添加节点
    head.Next.Next.Next = &ListNode{Val: 789}
  • java代码

     head.next.next = new ListNode(456);  //给head 指针变量指向节点的 下下节点 添加节点
     head.next.next.next = new ListNode(789);
  • Python代码

    head.next.next = ListNode(456)  # 给head 指针变量指向节点的 下下节点 添加节点
    head.next.next.next = ListNode(789)

添加2个节点之后,链表结构如下所示:

4、链表节点删除

链表结构如下所示:

如果要删除数据域为456、789的这样的两个节点,可以如下操作:

  • go代码:

    head.Next.Next = nil           // 通过head指针变量操作链表的指针域:截断链表
  • java代码

    head.next.next = null;  // 通过head指针变量操作链表的指针域:截断链表
  • Python代码

    head.next.next = None  # 通过head指针变量操作链表的指针域:截断链表

删除节点之后,链表结构如下所示:

经过操作系统的GC(Garbage Collection,垃圾收集器。用于自动管理内存并回收不再使用的对象所占用的资源)对不用的节点进行回收之后,链表结构如下图所示。

5、小结

今天对链表的基本操作进行了说明,其实还有很多需要加以了解的内容,如:链表打印、对链表的操作进行封装(操作链表更方便)等,鉴于篇幅的限制,再次就不展开了。

如果以上文字描述的不是很清楚或者想进一步了解链表相关操作,请参考视频详细讲解。

对于链表的相关操作,我们总结了一套【可视化+图解】方法,依据此方法来解决链表相关问题,链表操作变得易于理解,写出来的代码可读性高也不容易出错。具体也可以参考视频详细讲解。

今日佳句:雄关漫道真如铁,而今迈步从头越。


好易学数据结构
1 声望0 粉丝