【数据结构】认识链表和模拟实现单链表(2)

简介: 【数据结构】认识链表和模拟实现单链表

2.3 MyLinkedList类的成员方法

2.3.1 在链表开头插入一个新结点

在链表开头插入一个结点,首先需要根据 data 数据实例化一个结点。然后让这个新结点的 next 指针域存 head 的地址, 这样就让新的结点与后面的结点链接起来了,最后让 head 等于这个新结点,这样这个新结点就变成了第一个结点

//头插法
public void addFirst(int data) {
    Node nodeTmp = new Node(data);
    nodeTmp.next = this.head;
    this.head = nodeTmp;
}

2.3.2 获取链表的最后一个结点

首先 head 不能移动,如果移动第一个结点就会因没有被指向而回收,那么后面结点也就会因为没有被指向而被回收,所以需要创建一个临时的结点类型的变量 src,将 head 指向的结点赋值给它,这样 head 和 src 同时指向了第一个结点,当src 移动到其他结点,第一个结点还是会被 head 所指向。src 通过循环一直等于下一个结点,当 src 存储的结点的 next 为 null 时就为最后一个结点


//获取链表的最后一个结点
private Node lastNode() {
    Node src = this.head;
    while (src.next != null) {
        src = src.next;
    }
    return src;
}

注:这个方法是private修饰所以只能在 MyLinkedList类 中使用


2.3.3 在链表尾部插入一个新的结点

在链表尾部插入一个结点,首先需要这个链表是否为空,如果链表为 null ,尾插一个结点就相当于在链表开头插入一个结点。如果链表不为 null ,尾部插入一个结点就需要根据 data 数据实例化一个结点,然后通 lastNode 方法获取最后一个结点,让最后一个结点的 next 存储新结点的地址即可

//尾插法
public void addLast(int data) {
    if (head == null) {
        addFirst(data);
        return;
    }
    Node nodeTmp = new Node(data);
    Node last = lastNode();
    last.next = nodeTmp;
}

2.3.4  返回指定位置的前一个结点

首先判断位置是否合法,如果不合法直接返回 null ,否则用一个临时结点变量等于 head 指向的结点,然后通过循环 index - 1 次而找的指定位置的前一个结点


//返回指定位置的前一个结点
private Node prevNode(int index) {
    if (index > size() || index < 0) {
        return null;
    }
    Node src = this.head;
    while(index != 1) {
        src = src.next;
        index--;
    }
    return src;
}

2.3.5 在链表指定位置插入一个新结点

第一步判断指定位置是否合法,如果不合法直接返回 false。否则进入第二步判断插入的位置是否为第一个结点位置,如果是就直接采用头插法在链表的开头插入一个结点。否则进入第三步判断插入的位置是否为最后一个结点的下一个位置,如果是就直接采用尾插法在链表的尾部插入一个结点。否则就在实例化一个 data 数据结点,调用 preNode 方法获取指定位置的前一个结点,在用一个临时变量去存储前一个结点的后一个结点,让前一个结点的 next 存储这个新的结点地址,再让这个新的结点的 next 存储后一个结点地址即可




//任意位置插入,第一个数据结点为0号下标
public boolean addIndex(int index,int data) {
    if (index > size() || index < 0) {
        return false;
    } else if (index == 0) {
        addFirst(data);
    } else if (index == size()) {
        addLast(data);
    } else {
        Node nodeTmp = new Node(data);
        Node prev = prevNode(index);//指定位置前一个结点
        Node tmp = prev.next;//指定位置的结点
        prev.next = nodeTmp;
        nodeTmp.next = tmp;
    }
    return true;
}


注:if...else if...else if...else...这种多判断只会执行其中的一个


2.3.6  判断是否需要删除第一个结点

判断数据 key 是否与第一个结点数据域中的数据相同,如果相同则让head等于head.next,这样head就指向了下一个结点,也就删除了第一个结点


//判断第一个结点是否是指定的结点,如果是则删除第一个结点
private boolean judgeFistNode(int key) {
    if (key == this.head.data) {
        this.head = this.head.next;
        return true;
    }
    return false;
}

2.3.6 删除第一次出现的指定数据的结点

首先判断这个链表是否为 null,否则就判断指定数据的结点是否为链表的第一个结点,否则就通过两个结点变量去找这个数据结点以及它的前一个结点,找到之后让它的前一个结点的 next 存储它后结点的地址然后直接return,因为只删除第一次输出的指定数据的结点。如果遍历完都没有找到这个数据结点则没有这个数据结点


//删除第一次出现关键字为key的节点
public void remove(int key) {
    if (this.head == null) {
        return;
    }
    boolean judge = judgeFistNode(key);
    if (judge == true) {
        return;
    }
    Node src = this.head;
    Node slow = this.head;
    while (src != null) {
        if (src.data != key) {
            slow = src;
            src = src.next;
        } else {
            slow.next = src.next;
            return;
        }
    }
}


2.3.7 删除所有指定数据的结点

首先判断这个链表是否为 null, 否则就通过两个结点变量去找这个数据结点以及它的前一个结点,找到之后让它的前一个结点的 next 存储它后结点的地址,一直遍历完,因为要删除所有指定数据的结点。遍历完后在判断第一个结点是否为空,也就相当于如果第一个结点是要删除的结点,先不管它,先删后面的在删第一个结点


//删除所有值为key的节点
public void removeAllKey(int key) {
    if (this.head == null) {
        return;
    }
    Node src = this.head;
    Node slow = this.head;
    while (src != null) {
        if (src.data != key) {
            slow = src;
            src = src.next;
        } else {
            slow.next = src.next;
            src = src.next;
        }
    }
    judgeFistNode(key);
}


2.3.8 查找链表中是否有指定的数据

直接将这个链表遍历一遍,如果有直接返回 true,否则返回 false


//查找是否包含关键字key是否在单链表当中
public boolean contains(int key) {
    Node src = this.head;
    while (src != null) {
        if (src.data == key) {
            return true;
        }
        src = src.next;
    }
    return false;
}

2.3.9 获取链表的长度

直接将这个链表遍历一遍用一个整型变量计数即可


//得到单链表的长度
public int size() {
    Node src = this.head;
    int count = 0;
    while (src != null) {
        count++;
        src = src.next;
    }
    return count;
}

2.3.10 打印链表

首先判断这个链表是否为 null ,如果为空直接打印 null。否则将这个链表遍历一遍,打印每个结点数据域中的数据

//打印链表
public void display() {
    if (this.head == null) {
        System.out.print("null");
    }
    Node src = head;
    while (src != null) {
        System.out.print(src.data + " ");
        src  = src.next;
    }
    System.out.println();
}

2.3.11 清空链表

直接让 head 指向 null,这样第一个结点就没有被指向了,会直接被编译器回收。第一个结点被回收了,第二个结点也就没有被指向了也会被回收,依次如此,直到将整个链表全部回收


//清除链表
public void clear() {
    this.head = null;
}


相关文章
|
2月前
|
存储 算法 Perl
数据结构实验之链表
本实验旨在掌握线性表中元素的前驱、后续概念及链表的建立、插入、删除等算法,并分析时间复杂度,理解链表特点。实验内容包括循环链表应用(约瑟夫回环问题)、删除单链表中重复节点及双向循环链表的设计与实现。通过编程实践,加深对链表数据结构的理解和应用能力。
65 4
|
9天前
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
70 5
|
2月前
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
116 4
|
2月前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之单双链表精题详解(9)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
2月前
|
存储 Web App开发 算法
2024重生之回溯数据结构与算法系列学习之单双链表【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构之单双链表按位、值查找;[前后]插入;删除指定节点;求表长、静态链表等代码及具体思路详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
2月前
|
算法
数据结构之购物车系统(链表和栈)
本文介绍了基于链表和栈的购物车系统的设计与实现。该系统通过命令行界面提供商品管理、购物车查看、结算等功能,支持用户便捷地管理购物清单。核心代码定义了商品、购物车商品节点和购物车的数据结构,并实现了添加、删除商品、查看购物车内容及结算等操作。算法分析显示,系统在处理小规模购物车时表现良好,但在大规模购物车操作下可能存在性能瓶颈。
53 0
|
3月前
|
存储
[数据结构] -- 单链表
[数据结构] -- 单链表
29 1
|
2月前
|
C语言
【数据结构】双向带头循环链表(c语言)(附源码)
本文介绍了双向带头循环链表的概念和实现。双向带头循环链表具有三个关键点:双向、带头和循环。与单链表相比,它的头插、尾插、头删、尾删等操作的时间复杂度均为O(1),提高了运行效率。文章详细讲解了链表的结构定义、方法声明和实现,包括创建新节点、初始化、打印、判断是否为空、插入和删除节点等操作。最后提供了完整的代码示例。
78 0
|
3月前
|
存储
[数据结构] -- 双向循环链表
[数据结构] -- 双向循环链表
28 0

热门文章

最新文章