链表里的数据是以节点的方式表示的,每一个结点的组成是由:元素+指针来组成的,元素就是存储数据里的存储单元,指针就是用来连接每一个结点的地址数据。这个以结点的序列来表示线性表被称作为单链表。
单链表是一种链式储存结构。在物理储存单元不连续,非顺序。
末尾增加元素 | void add(T data) |
---|---|
指定下标增加元素 | void add(int index,T data) |
删除指定下标元素 | void delete(int index) |
获取指定下标的元素 | T get(int index) |
修改指定下标的元素 | void update(int index,T data) |
遍历输出所有元素 | void show() |
获取链表的长度 | int length() |
(1)定义数据节点实体
(2)向链表末尾增加元素
(3)指定下标向链表增加元素
(4)删除指定下标元素的数据
(5)修改指定下标的元素
(6)获取指定下表的元素
(7)循环遍历输出
(8)获取当前有效的元素个数
(1)整体代码实现
public class SingleLinkedList {/*** 定义头节点*/public Node head = new Node<>(null);/*** 链表有效元素个数*/private int length=0;/*** 向单链表中添加一个元素* @param data*/public void add(T data){//定义当前数据Node nodeData = new Node<>(data);//定义辅助指针Node cur = head;//while 循环不断遍历找到最后一个节点while (cur.next != null) {//只要有下一个节点,辅助指针就向下移动一位cur = cur.next;}//while循环之后,cur已经是最后一个节点,将data赋值到cur的下一个节点上cur.next = nodeData;//整体链表长度++length++;}/*** 向单链表中添加一个元素* @param data*/public void add(int index,T data){//判断index是否合法if(index <0 || index >length){System.out.println("index不合法");return;}//定义当前数据Node nodeData = new Node<>(data);//定义辅助指针Node cur = head;//找到当前index的元素for (int i = 0; i < index; i++) {cur = cur.next;}//将当前节点的next设置成cur的nextnodeData.next = cur.next;//将cur.next设置成nodeData(当前节点)cur.next = nodeData;//整体链表长度++length++;}/*** 遍历输出链表中全部节点*/public void show(){//定义辅助指针Node cur = head;//判断链表中是否存在元素if (cur.next == null){System.out.println("当前单向链表中元素为空");return;}while (cur.next != null){System.out.print(cur.next.data+" ");cur = cur.next;}System.out.print("\n");}/*** 修改指定下标的数据* @param index* @param data*/public void update(int index,T data){Node cur = head;if(index > length){System.out.println("当前index查过边界");return;}//遍历寻找指定index的节点for (int i = 0; i <= index; i++) {cur = cur.next;}//找到之后将新的data赋值上去cur.data = data;}/*** 删除指定下标元素* @param data*/public void delete(int index){Node cur = head;if(index > length){System.out.println("当前index超过边界");return;}//遍历寻找指定index的节点for (int i = 0; i < index; i++) {cur = cur.next;}//找到之后将新的data赋值上去,将后一个data赋值到当前节点上cur.data = cur.next.data;//将当前节点的next变成当前节点的next.next相当于将当前元素的next节点删掉cur.next = cur.next.next;//单链表整体有效元素减一length--;}/*** 获取指定下标元素的数据* @param index* @return*/public T get(int index){//校验参数是否合法if(index<0 || index>length){System.out.println("当前index超过边界");}//定义辅助节点Node cur = head;//找到对应下标的nodefor (int i = 0; i <=index; i++) {cur = cur.next;}//返回node.datareturn cur.data;}/*** 获取单链表的长度* @return*/public int length(){return this.length;}/*** 内部节点类* @param */class Node{/*** 定义数据*/public T data;/*** 定义下一个节点的*/public Node next;public Node(T data) {this.data = data;}}
}
(2)测试代码
public class Main {public static void main(String[] args) {SingleLinkedList singleLink = new SingleLinkedList<>();//增加元素singleLink.add(1);singleLink.add(2);singleLink.add(3);System.out.print("新增之后:");singleLink.show();//删除元素singleLink.delete(0);System.out.print("删除index为0之后:");singleLink.show();//修改元素singleLink.update(0,9);System.out.print("修改index为0之后:");singleLink.show();//获取单链表的长度int length = singleLink.length();System.out.println("单链表的长度:"+length);//获取指定下标的数据System.out.println("获取指定下标的数据:"+singleLink.get(1));//指定下标插入数据singleLink.add(1,6);System.out.print("在index为1位置插入数据之后:");singleLink.show();}
}
优点:
链表的内存空间不连续。
如果知道要处理节点的前一个位置,则进行插入和删除的复杂度为O(1);
如果不知道要处理节点的前一个位置,则进行插入和删除的复杂度为O(N)。
头插、头删的效率高,时间复杂度是O(1)。
没有空间限制,不会溢出,可以存储很多元素。
缺点: