什么是链表
- 数组和链表是数据结构的基础,链表是物理存储单元上非连续的、非顺序的存储结构,它是由一个个结点,通过指针来联系起来的,其中每个结点包括数据和指针,而数组则是开辟一块连续的内存。链表的非连续,非顺序,对应了数组的连续,顺序。
- 链表的查询或删除元素都要从头结点开始,所以我们只要在链表中定义头结点即可,另外如果要频繁用到链表的长度,还可以额外定义一个Size变量来表示。
链表注意的点
链表的头结点一般有两种定义形式,一种是直接以某个元素结点为头节点,如图:
public void putNode(int value) {
// 头节点为空校验
if (head == null) {
head = new Node(value);
} else {
Node temp = head;
while (temp.next != null) {
temp.next = temp;
}
temp.next = new Node(value);
}
}
第二种是以虚拟头节点头为头的节点,如图:
Node head = new Node(0); // 虚拟节点
public void putNode(int value) {
Node temp = head;
while (temp.next != null) {
temp.next = temp;
}
temp.next = new Node(value);
}
定义了虚拟节点之后,就不用每次插入元素都对头结点进行判空了。
代码简单实现一个链表的添加
public class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}
public class Solution {
ListNode head = new ListNode(0); // 虚拟节点
public static void main(String[] args) {
ListNode listNode = new ListNode();
// 方法一、以首节点为节点
for (int i = 0; i < 10; i++) {
ListNode node = new ListNode(i);
if (listNode.next == null){
node.next = listNode.next;
listNode.next = node;
}else {
node.next = listNode.next;
listNode.next = node;
}
}
// 方法二、以虚拟节点为节点
for (int i = 0; i < 10; i++) {
ListNode newNode = new ListNode(i);
// 2.新结点指向头结点之后的结点
newNode.next = head.next;
// 3.头结点指向新结点
head.next = newNode;
}
}
}
代码实现链表的增删改查
/**
* 创建节点类
*/
private class Node{
Integer value;
Node next;
public Node(Integer val,Node next){
this.value = val;
this.next = next;
}
public Node(Integer value){
this(value,null);
}
public Node(){
this(null,null);
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
", next=" + next +
'}';
}
}
链表增删改查:
/**
* 链表
*/
public class Book008 {
// 虚拟头节点
Node dummyNode;
// 节点的个数
int size;
public Book008(){
this.dummyNode = new Node();
this.size = 0;
}
/**
* 添加节点
* @param index
* @param val
*/
public void addElement(int index, int val){
if (index < 0 || index > size){
throw new IllegalArgumentException("索引值不合法!");
}
Node temp = dummyNode;
for (int i = 0; i < index; i++) {
temp = temp.next;
}
// 1、先让要添加的节点指向temp的下一个节点
Node newNode = new Node(val,temp.next);
// 2、再将temp的next指向node
temp.next = newNode;
size++;
}
/**
* 删除节点
* @param index
*/
public int delElement(int index){
if (index < 0 || index > size){
throw new IllegalArgumentException("索引值不合法!");
}
Node temp = dummyNode;
for (int i = 0; i < index; i++) {
temp = temp.next;
}
Node nextNode = temp.next;
int result = nextNode.value;
temp.next = nextNode.next;
nextNode.next = null;
size --;
return result;
}
/**
* 修改元素
* @param index
* @param val
* @return
*/
public void updateElement(int index,int val){
// 校验省略
Node temp = dummyNode.next;
for (int i = 0; i < index; i++) {
temp = temp.next;
}
temp.value = 12;
}
/**
* 获取元素
* @param index
* @return
*/
public int getElement(int index){
// 校验省略
Node node = dummyNode.next;
for(int i = 0 ; i < index ; i ++)
node = node.next;
return node.value;
}
/**
* 获取第一个元素
* @return
*/
public int getFirst(){
return getElement(0);
}
/**
* 获取最后一个元素
* @return
*/
public int getLast(){
return getElement(size - 1);
}
/**
* 是否包含
* @param val
* @return
*/
public boolean isContain(int val){
Node tempNode = dummyNode.next;
while (tempNode != null){
if (tempNode.value == val){
return true;
}
tempNode = tempNode.next;
}
return false;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder("链表信息:");
Node temp = dummyNode.next;
while (temp != null){
builder.append(temp.value).append("-->");
temp = temp.next;
}
builder.append("NULL");
return builder.toString();
}
public static void main(String[] args) {
Book008 book008 = new Book008();
for (int i = 0; i < 5; i++) {
book008.addElement(i,i+1);
}
// 循环添加节点
System.out.println(book008);
// 添加节点
book008.addElement(2,10);
System.out.println(book008);
// 删除节点
int result = book008.delElement(2);
System.out.println("删除节点:"+result+" 之后: " + book008);
// 修改节点
book008.updateElement(3,12);
System.out.println("修改节点: " + book008);
// 判断节点是否存在
boolean contain = book008.isContain(2);
System.out.println("是否包含该元素:" + contain);
System.out.println("获取某一个元素:" + book008.getElement(2));
System.out.println("获取第一个元素:" + book008.getFirst());
System.out.println("获取最后一个元素:" + book008.getLast());
}
}
打印输出