链表介绍
- 链表(linked list)是一种在物理上非连续,非顺序的数据结构,由若干节点(node)组成
- 单链表每一个节点又包含两部分,1是存放数据的变量data,2是存放指向下一个结点的指针next
- 双向链表每一个节点包含三部分,在单链表的基础上多了一个指向前置节点的prev指针
- 链表的第一个节点被称为头节点,最后一个节点被称为尾节点,尾结点的next指针指向null
- 链表在内存中的存储方式为随机存储
时间复杂度
- 不考虑插入,删除操作之前的查找元素的过程,只考虑插入和删除,时间复杂度为O(1)
- 链表的查找从头结点开始,链表的长度越大,查找的时间越长,时间复杂度为O(n)
对比数组和链表
数组优势在于快速定位元素,对于读操作多,写操作少的场景,数组更合适
链表优势在于快速的插入和删除操作,如果频繁的在尾部删除和插入元素,用链表更好
单链表demo
package com.cc.node;
public class NodeDemo1 {
//内部类,只能在内部访问使用
private static class Node {
int data;
Node next;
public Node(int data) {
this.data = data;
}
}
private Node head;
private Node last;
//链表的实际长度
private int size;
/**
* 链表插入元素
*
* @param index
* @param data
* @throws Exception
*/
public void insert(int index, int data) throws Exception {
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("超出链表的节点范围");
}
Node insertNode = new Node(data);
//空链表
if (size == 0) {
head = insertNode;
last = insertNode;
} else if (index == 0) {
//插入头部
//分为两步:1.把新节点的next指针指向原head节点,2.把新节点变为链表的头节点
insertNode.next = head;
head = insertNode;
} else if (index > 0 && index < size - 1) {
//中间插入
//分两步:1.把新节点的next指针指向插入位置的节点,2.插入位置的前置节点的next指针指向新节点
Node prevNode = getNode(index - 1);//前置节点
insertNode.next = prevNode.next;//新节点指向插入位置的节点
prevNode.next = insertNode;//前置节点指向新节点
} else {
//插入尾部
//分两步,1.最后一个节点的next指针指向新节点,2.把新节点指向尾部节点
last.next = insertNode;
last = insertNode;
}
//链表的长度加1
size++;
}
/**
* 删除链表中指定位置的节点
*
* @param index
* @throws Exception
*/
public void deleteNode(int index) throws Exception {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("超出链表的节点范围");
}
Node deleteNode = null;
if (index == 0) {
//头部删除节点
//链表的头节点设为原先头节点的next指向的节点
head = head.next;
} else if (index > 0 && index < size - 1) {
//删除中间的节点
//插入位置的前一个节点,指向插入插入位置的下一个节点
Node prevNode = getNode(index - 1);
prevNode.next = prevNode.next.next;
} else {
//删除尾部节点
//获取尾部的前一个节点,1.倒数第二个节点next指向空,2.尾节点指向倒数第二个节点
Node prevNode = getNode(index - 1);
prevNode.next = null;
last = prevNode;
}
size--;
}
/**
* 链表中查找指定位置的节点
*
* @param index
* @return
* @throws Exception
*/
public Node getNode(int index) throws Exception {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("超出链表的节点范围");
}
//链表的查找从头节点开始
Node temp = head;
for (int i = 0; i < index; i++) {
temp = temp.next;
}
return temp;
}
/**
* 输出链表中的所有数据
*/
public void outList() {
Node temp = head;
for (int i = 0; i < size; i++) {
System.out.println(temp.data);
temp = temp.next;
}
}
public static void main(String[] args) throws Exception {
NodeDemo1 linkedlist = new NodeDemo1();
linkedlist.insert(0, 1);
linkedlist.insert(1, 2);
linkedlist.insert(2, 3);
linkedlist.insert(3, 4);
linkedlist.insert(4, 5);
linkedlist.insert(5, 6);
linkedlist.outList();
linkedlist.deleteNode(5);
linkedlist.outList();
}
}