单向链表的缺点分析
- 单向链表,查找的方向只能是一个方向,而双向链表可以向前或者向后查找。
- 单向链表不能自我删除,需要靠辅助节点 ,而双向链表,则可以自我删除。
对上图的说明:
- 遍历方和 单链表一样,只是可以向前,也可以向后查找
- 添加 (默认添加到双向链表的最后)
- 先找到双向链表的最后这个节点
- temp.next = newHeroNode
- newHeroNode.pre = temp
- 修改 思路和 原来的单向链表一样
- 删除
- 因为是双向链表,因此,我们可以实现自我删除某个节点
- 直接找到要删除的这个节点,比如 temp
- temp.pre.next = temp.next
- temp.next.pre = temp.pre
/**
* @date 2021/03/04
*/
public class DoubleLinkedListDemo {
public static void main(String[] args) {
DoubleLinkedList<Hero2> linkedList = new DoubleLinkedList<>();
Hero2 hero1 = new Hero2(1, "宋江", "及时雨");
Hero2 hero2 = new Hero2(2, "卢俊义", "玉麒麟");
Hero2 hero3 = new Hero2(3, "吴用", "智多星");
Hero2 hero4 = new Hero2(4, "林冲", "豹子头");
Hero2 hero5 = new Hero2(5, "林冲4", "豹子头4");
Hero2 hero6 = new Hero2(6, "林冲6", "豹子头6");
Hero2 hero7 = new Hero2(7, "林冲7", "豹子头7");
Hero2 hero8 = new Hero2(8, "林冲8", "豹子头8");
Hero2 hero9 = new Hero2(9, "林冲9", "豹子头9");
System.out.println("尾部插入:");
linkedList.append(hero1);
linkedList.append(hero4);
linkedList.append(hero3);
linkedList.append(hero2);
linkedList.show();
System.out.println("----------------");
System.out.println("顺序插入:");
linkedList.clear();
linkedList.insert(hero1);
linkedList.insert(hero4);
linkedList.insert(hero3);
linkedList.insert(hero2);
linkedList.insert(hero6);
linkedList.insert(hero8);
linkedList.insert(hero5);
linkedList.insert(hero9);
linkedList.insert(hero7);
linkedList.show();
System.out.println("----------------");
System.out.println("更新吴用为吴勇:");
linkedList.update(new Hero2(3, "吴勇", "憨憨"));
System.out.println("更新林冲为林冲Plus:");
linkedList.update(new Hero2(4, "林冲Plus", "铁头娃"));
System.out.println("更新结果:");
System.out.println(linkedList.query(3));
System.out.println(linkedList.query(4));
System.out.println("----------------");
System.out.println("删除吴勇:");
System.out.println("删除林冲7:");
System.out.println("删除林冲9:");
linkedList.delete(7);
linkedList.delete(9);
linkedList.delete(3);
linkedList.show();
}
}
class DoubleLinkedList<T> {
private int size;
Node<T> head;
public DoubleLinkedList() {
this.size = 0;
// 头结点数据域为空
this.head = new Node<>(null, 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,tempHead);
this.size++;
break;
}
tempHead = tempHead.next;
}
}
/**
* 插入元素,根据英雄编号从小到大排序
*
* @param data
*/
public void insert(T data) {
// 若data不是Hero类则不会执行该方法
if(data.getClass() == Hero2.class){
Node<T> tempHead = this.head;
while (true) {
// 没有下一个节点了,则在下一个节点插入数据
if (tempHead.next == null) {
tempHead.next = new Node<>(data, null,tempHead);
this.size++;
break;
}else {
Hero2 h1 = (Hero2) data;
Hero2 h2 = (Hero2) tempHead.next.item;
// 排序
if(h1.getNo() <= h2.getNo()){
// tempHead.next指向新插入的数据,新插入的数据指向tempHead.next
tempHead.next = new Node<>(data, tempHead.next,tempHead);
this.size++;
break;
}
}
tempHead = tempHead.next;
}
}
else {
this.append(data);
}
}
public void update (T data){
// 更新只针对Hero类
if (data.getClass() == Hero2.class){
Node<T> tempHead = this.head;
while (true){
if(tempHead.next == null){
return;
}
Hero2 oldHero = (Hero2) tempHead.next.item;
Hero2 newHero = (Hero2)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 Hero2){
Hero2 hero = (Hero2) t;
if(hero.getNo() == no){
if(tempHead.next.next == null){
tempHead.next = null;
}
else {
tempHead.next = tempHead.next.next;
tempHead.next.pre = tempHead;
}
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 Hero2){
Hero2 hero = (Hero2) 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("----");
// System.out.println("pre指针指向:" +tempHead.item);
System.out.println("当前节点:" +tempHead.next.item);
// if(tempHead.next.next != null){
// System.out.println("next指针指向:" + tempHead.next.next.item);
// }
// else {
// System.out.println("next指针指向无数据");
// }
tempHead = tempHead.next;
// System.out.println("----");
}
}
public void clear(){
this.size = 0;
// 头结点数据域为空
this.head = new Node<>(null, null,null);
}
/**
* 链表节点
*
* @param <T>
*/
static private class Node<T> {
/**
* 数据域
*/
T item;
/**
* 指向写一个节点
*/
Node<T> next;
/**
* 指向后一个节点
*/
Node<T> pre;
public Node(T item, Node<T> next, Node<T> pre) {
this.item = item;
this.next = next;
this.pre = pre;
}
}
}
/**
* 实体类
*
*/
class Hero2 {
private int no;
private String name;
private String nickname;
public Hero2(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 "Hero2{" +
"no=" + no +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}
打印内容:
尾部插入:
当前节点:Hero2{no=1, name=‘宋江’, nickname=‘及时雨’}
当前节点:Hero2{no=4, name=‘林冲’, nickname=‘豹子头’}
当前节点:Hero2{no=3, name=‘吴用’, nickname=‘智多星’}
当前节点:Hero2{no=2, name=‘卢俊义’, nickname=‘玉麒麟’}
----------------
顺序插入:
当前节点:Hero2{no=1, name=‘宋江’, nickname=‘及时雨’}
当前节点:Hero2{no=2, name=‘卢俊义’, nickname=‘玉麒麟’}
当前节点:Hero2{no=3, name=‘吴用’, nickname=‘智多星’}
当前节点:Hero2{no=4, name=‘林冲’, nickname=‘豹子头’}
当前节点:Hero2{no=5, name=‘林冲4’, nickname=‘豹子头4’}
当前节点:Hero2{no=6, name=‘林冲6’, nickname=‘豹子头6’}
当前节点:Hero2{no=7, name=‘林冲7’, nickname=‘豹子头7’}
当前节点:Hero2{no=8, name=‘林冲8’, nickname=‘豹子头8’}
当前节点:Hero2{no=9, name=‘林冲9’, nickname=‘豹子头9’}
----------------
更新吴用为吴勇:
更新林冲为林冲Plus:
更新结果:
Hero2{no=3, name=‘吴勇’, nickname=‘憨憨’}
Hero2{no=4, name=‘林冲Plus’, nickname=‘铁头娃’}
----------------
删除吴勇:
删除林冲7:
删除林冲9:
当前节点:Hero2{no=1, name=‘宋江’, nickname=‘及时雨’}
当前节点:Hero2{no=2, name=‘卢俊义’, nickname=‘玉麒麟’}
当前节点:Hero2{no=4, name=‘林冲Plus’, nickname=‘铁头娃’}
当前节点:Hero2{no=5, name=‘林冲4’, nickname=‘豹子头4’}
当前节点:Hero2{no=6, name=‘林冲6’, nickname=‘豹子头6’}
当前节点:Hero2{no=8, name=‘林冲8’, nickname=‘豹子头8’}