链表(Linked List)介绍
链表是有序的列表,但是它在内存中是存储如下
- 链表是以节点的方式来存储,是链式存储
- 每个节点包含 data 域, next 域:指向下一个节点.
- 如图:发现链表的各个节点不一定是连续存储.
- 链表分带头节点的链表和没有头节点的链表,根据实际的需求来确定
单链表(带头结点) 逻辑结构示意图如下
单链表简单实现:
/**
* 单向链表
*
* @date 2021/02/24
*/
public class SingleLinkedListDemo {
public static void main(String[] args) {
Hero hero1 = new Hero(1, "宋江", "及时雨");
Hero hero2 = new Hero(2, "卢俊义", "玉麒麟");
Hero hero3 = new Hero(3, "吴用", "智多星");
Hero hero4 = new Hero(4, "林冲", "豹子头");
Hero hero5 = new Hero(4, "林冲4", "豹子头4");
Hero hero6 = new Hero(6, "林冲6", "豹子头6");
Hero hero7 = new Hero(7, "林冲7", "豹子头7");
Hero hero8 = new Hero(8, "林冲8", "豹子头8");
Hero hero9 = new Hero(9, "林冲9", "豹子头9");
//创建链表
SingleLinkedList<Hero> singleLinkedList = new SingleLinkedList<>();
// 添加到链表尾部
// singleLinkedList.append(hero1);
// singleLinkedList.append(hero4);
// singleLinkedList.append(hero2);
// singleLinkedList.append(hero3);
/*
打印的数据无排序:
Hero{no=1, name='宋江', nickname='及时雨'}
Hero{no=4, name='林冲', nickname='豹子头'}
Hero{no=2, name='卢俊义', nickname='玉麒麟'}
Hero{no=3, name='吴用', nickname='智多星'}
*/
// singleLinkedList.show();
// singleLinkedList.insert(hero3);
// singleLinkedList.insert(hero2);
// singleLinkedList.insert(hero4);
// singleLinkedList.insert(hero1);
// singleLinkedList.insert(hero5);
// singleLinkedList.insert(hero6);
// singleLinkedList.insert(hero7);
// singleLinkedList.insert(hero8);
// singleLinkedList.insert(hero9);
/*
打印出的数据已经排好序了:
Hero{no=1, name='宋江', nickname='及时雨'}
Hero{no=2, name='卢俊义', nickname='玉麒麟'}
Hero{no=3, name='吴用', nickname='智多星'}
Hero{no=4, name='林冲4', nickname='豹子头4'}
Hero{no=4, name='林冲', nickname='豹子头'}
Hero{no=6, name='林冲6', nickname='豹子头6'}
Hero{no=7, name='林冲7', nickname='豹子头7'}
Hero{no=8, name='林冲8', nickname='豹子头8'}
Hero{no=9, name='林冲9', nickname='豹子头9'}
*/
singleLinkedList.insert(hero3);
singleLinkedList.insert(hero2);
singleLinkedList.insert(hero4);
singleLinkedList.insert(hero1);
System.out.println("更新前:");
singleLinkedList.show();
singleLinkedList.update(new Hero(4,"新林冲","新豹子头"));
singleLinkedList.update(new Hero(3, "新吴用", "新智多星"));
System.out.println("更新后:");
singleLinkedList.show();
/*
更新前:
Hero{no=1, name='宋江', nickname='及时雨'}
Hero{no=2, name='卢俊义', nickname='玉麒麟'}
Hero{no=3, name='吴用', nickname='智多星'}
Hero{no=4, name='林冲', nickname='豹子头'}
更新后:
Hero{no=1, name='宋江', nickname='及时雨'}
Hero{no=2, name='卢俊义', nickname='玉麒麟'}
Hero{no=3, name='新吴用', nickname='新智多星'}
Hero{no=4, name='新林冲', nickname='新豹子头'}
*/
singleLinkedList.delete(2);
System.out.println("删除no为2后:");
singleLinkedList.show();
/*
删除no为2后:
Hero{no=1, name='宋江', nickname='及时雨'}
Hero{no=3, name='新吴用', nickname='新智多星'}
Hero{no=4, name='新林冲', nickname='新豹子头'}
*/
System.out.println("查找no为3:");
System.out.println(singleLinkedList.query(3));
/*
查找no为3:
Hero{no=3, name='新吴用', nickname='新智多星'}
*/
}
}
class SingleLinkedList<T> {
private int size;
Node<T> head;
public SingleLinkedList() {
this.size = 0;
// 头结点数据域为空
this.head = new Node<>(null, null);
}
/**
* 在链表尾部添加数据
*
* @param data
*/
public void append(T data) {
Node<T> tempHead = this.head;
while (true) {
// 没有下一个节点了,则在下一个节点插入数据
if (tempHead.next == null) {
tempHead.next = new Node<>(data, null);
this.size++;
break;
}
tempHead = tempHead.next;
}
}
/**
* 插入元素,根据英雄编号从小到大排序
*
* @param data
*/
public void insert(T data) {
// 若data不是Hero类则不会执行该方法
if(data.getClass() == Hero.class){
Node<T> tempHead = this.head;
while (true) {
// 没有下一个节点了,则在下一个节点插入数据
if (tempHead.next == null) {
tempHead.next = new Node<>(data, null);
this.size++;
break;
}else {
Hero h1 = (Hero) data;
Hero h2 = (Hero) tempHead.next.item;
// 排序
if(h1.getNo() <= h2.getNo()){
// tempHead.next指向新插入的数据,新插入的数据指向tempHead.next
tempHead.next = new Node<>(data, tempHead.next);
this.size++;
break;
}
}
tempHead = tempHead.next;
}
}
else {
this.append(data);
}
}
public void update (T data){
// 更新只针对Hero类
if (data.getClass() == Hero.class){
Node<T> tempHead = this.head;
while (true){
if(tempHead.next == null){
return;
}
Hero oldHero = (Hero) tempHead.next.item;
Hero newHero = (Hero)data;
if(oldHero.getNo() ==newHero.getNo()){
tempHead.next.item = data;
return;
}
tempHead = tempHead.next;
}
}
}
/**
* 删除
*
* @param no
* @return
*/
public void delete(int no){
if(no < 0){
return ;
}
Node<T> tempHead = this.head;
while (true){
if(tempHead.next == null){
return ;
}
T t = tempHead.next.item;
if(t instanceof Hero){
Hero hero = (Hero) t;
if(hero.getNo() == no){
tempHead.next = tempHead.next.next;
this.size--;
return ;
}
}
tempHead = tempHead.next;
}
}
/**
* 查找
*
* @param no
* @return
*/
public T query(int no){
if(no < 0){
return null;
}
Node<T> tempHead = this.head;
while (true){
if(tempHead.next == null){
return null;
}
T t = tempHead.next.item;
if(t instanceof Hero){
Hero hero = (Hero) t;
if(hero.getNo() == no){
return t;
}
}
tempHead = tempHead.next;
}
}
/**
* 链表长度
* @return
*/
public int size() {
return this.size;
}
/**
* 查看链表数据
*/
public void show() {
Node<T> tempHead = this.head;
while (tempHead.next != null) {
System.out.println(tempHead.next.item);
tempHead = tempHead.next;
}
}
/**
* 链表节点
*
* @param <T>
*/
static private class Node<T> {
/**
* 数据域
*/
T item;
/**
* 指针域
*/
Node<T> next;
public Node(T item, Node<T> next) {
this.item = item;
this.next = next;
}
}
}
/**
* 实体类
*
*/
class Hero {
private int no;
private String name;
private String nickname;
public Hero(int no, String name, String nickname) {
this.no = no;
this.name = name;
this.nickname = nickname;
}
public int getNo() {
return no;
}
@Override
public String toString() {
return "Hero{" +
"no=" + no +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}