java -数据结构,单向链表
创始人
2024-03-08 16:04:53
0

顺序表的问题及思考:

  1. 顺序表中间/头部的插入删除,时间复杂度为O(N)
  2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
  3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间

思考: 如何解决以上问题呢?下面给出了链表的结构来看看

一、链表

1.1、链表的概念及结构

链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的
在这里插入图片描述

在这里插入图片描述

1.1.1、创建一个类表示节点 - ListNode

//NodeList 表示节点 类
class ListNode{//值域public int val;//下一个节点的地址public ListNode next;public ListNode(int val){this.val = val;}
}

在这里插入图片描述

1.1.2、创建一个类来表示链表 - MyLinkedList

//ListNode 表示节点 类
class ListNode{//值域public int val;//下一个节点的地址public ListNode next;public ListNode(int val){this.val = val;}
}public class MyLinkedList {public static void main(String[] args) {//当new 一个节点的时候就是创建一个节点,值为 1ListNode nodeList = new ListNode(1);}
}

new 一个节点

如和创建多个节点,让这些节点串起来

首先要有一个头结点

单向,带头,不循环的单链表
在这里插入图片描述

理解链表中: 带头、不带头、单向、双向、循环、不循环的意思

带头 和 不带头

在这里插入图片描述

循环 和 不循环

在这里插入图片描述

单向 和 双向

在这里插入图片描述

1.1.3、模拟实现 单向 不带头 非循环的链表

在这里插入图片描述

用过列举的方式,创建几个节点,然后将他们连接起来

//ListNode 表示节点 类
class ListNode{//值域public int val;//下一个节点的地址public ListNode next;public ListNode(int val){this.val = val;}
}public class MyLinkedList {public ListNode head;//创建5个节点的链表public void creatList(){//当new 一个节点的时候就是创建一个节点,值为 1ListNode ListNode1 = new ListNode(10);ListNode ListNode2 = new ListNode(20);ListNode ListNode3 = new ListNode(30);ListNode ListNode4 = new ListNode(40);ListNode ListNode5 = new ListNode(50);ListNode1.next = ListNode2;ListNode2.next = ListNode3;ListNode3.next = ListNode4;ListNode4.next = ListNode5;this.head = ListNode1;}
}

在这里插入图片描述
此时就有5个节点了

1.1.4、遍历链表数据

首先,我要区分清楚,链表 不是顺序表,不是一块连续的空间。 链表的每个元素 是由地址来连接起来的。
也就是说 我们不能使用普通思维模式 去思考 遍历链表的数据域的值

既然 链表是靠地址联系起来的,也就是说 靠 next域中 存储的地址来联系个节点的数据,
这就是我们突破点。
利用 head 遍历每个每个节点的数据 写法 head = head.next,你可以参考上面的图,来细品。
这样我们就跳转到下一个节点,算了我还是画个图,请看下图

//打印链表的数据public void disPlay(){ListNode cur = this.head;while(cur != null){System.out.print(cur.val + " " );cur = cur.next;}System.out.println();}

在这里插入图片描述

测试一下:

public class TestDome {public static void main(String[] args) {MyLinkedList myLinkedList = new MyLinkedList();myLinkedList.creatList();myLinkedList.disPlay();}
}

.2.1、

1.2、链表里面的操作

1.2.1、得到单链表的长度

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

1.2.2、头插法

//头插法public void addFirst(int data){ListNode node = new ListNode(data);node.next = head;head = node;};

在这里插入图片描述

1.2.3、尾插法

//尾插法public void addLast(int data){ListNode node = new ListNode(data);ListNode cur = this.head;//判断链表是否为空if(this.head == null){this.head = node;} else{while(cur.next != null){cur = cur.next;}cur.next = node;}};

在这里插入图片描述

1.2.4、查找是否包含关键字key是否在单链表当中

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

为

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

/任意位置插入,第一个数据节点为0号下标public void addIndex(int index,int data){ListNode node = new ListNode(data);if(index < 0 || index > size()){System.out.println("index 位置不合法!");return;}if(index == 0){addFirst(data);return;}if(index == size()){addLast(data);return;}//中间位置ListNode cur = this.head;while(index - 1 != 0){cur = cur.next;index--;}node.next = cur.next;cur.next = node;};

在这里插入图片描述

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

//删除第一次出现关键字为key的节点public void remove(int key){//当链表为空的时候if(size() == 0){System.out.println("删除失败,链表为空!");return;}//当删除的是头节点的时候if(this.head.val == key){this.head = this.head.next;return;}ListNode cur = this.head;while(cur.next != null){if(cur.next.val == key){cur.next = cur.next.next;return;}cur = cur.next;}return;};

在这里插入图片描述

1.2.7、删除所有值为key的节点

 //删除所有值为key的节点public void removeAllKey(int key){if(this.head == null){System.out.println("链表为空!");return;}//cur.val 就是删除的值ListNode prev = this.head;ListNode cur = this.head.next;while (cur != null){if(cur.val == key){prev.next = cur.next;cur = cur.next;}else{prev = cur;cur = cur.next;}}//删除头结点if(head.val == key){this.head = head.next;}};

在这里插入图片描述

1.2.8、清除单链表

清除链表里面的数据的时候,最好是一个节点一个节点的释放(置为null)

//清除单链表public void clear(){//粗暴的做法//this.head = null;while (this.head != null){ListNode curNext = this.head;this.head = null;head = curNext;}};

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...