package com.zejian.structures.LinkedList.MyLinked;
/**
* 双链表的工具类
*/
public class DNode<T> {
public T data;//存储的数据
public DNode<T> pre;//前指针
public DNode<T> next;//后指针
//构造方法 创建对象
public DNode(T data, DNode<T> pre, DNode<T> next) {
this.data = data;
this.pre = pre;
this.next = next;
}
/**
* 创建一个前指针、后指针为空的值
* @param data
*/
public DNode(T data) {
this(data,null,null);
}
/**
* 创建一个空值
*/
public DNode() {
this(null,null,null);
}
@Override
public String toString() {
return this.data.toString();
}
}
package com.zejian.structures.LinkedList.MyLinked;
public class DoubleLinkedList<T> implements ILinkedList<T> {
//设置头节点
private DNode<T> head;
//设置尾节点
private DNode<T> tail;
//构造方法初始化头结点尾节点值
public DoubleLinkedList() {
//设置为空值
this.head=this.tail=new DNode<>();
}
@Override
public boolean isEmpty() {
return false;
}
/**
* 长度
* @return
*/
@Override
public int length() {
int length=0;
DNode<T> pre=head.next;
while (pre!=null){
length++;
pre=pre.next;
}
return length;
}
@Override
public T get(int index) {
return null;
}
@Override
public T set(int index, T data) {
return null;
}
/**
* 插入结点
* @param index
* @param data
* @return
*/
@Override
public boolean add(int index, T data) {
DNode<T> font = this.head;//头节点是一个空节点,尾节点有tail控制
int j=0;
//找到插入节点的前一个节点j<index
while (font.next!=null&&j<index){
font=font.next;
j++;
}
//创建新的节点,在虚拟机中开辟了内存,创建了对象,
DNode<T> p = new DNode<>(data, font, font.next);//数据 数据的前节点 数据的后节点 ;传入的对象赋值给新对象的前节点和后节点
//改变前节点和后节点指针方向,新对象的内存地址赋值
font.next=p;
//尾节点或者是头节点不执行此操作
if (font.next!=null){
font.next.pre=p;
}
// p= font.next;
// p=font.next.pre;
//如果是尾节点,更新尾节点
if (font==tail){
this.tail=p;
}
return false;
}
/**
* 从尾部插入
* @param data
* @return
*/
@Override
public boolean add(T data) {
//空节点和头结点已经创建了,可以直接拿来用
if (data!=null){
//插入第一个数据
DNode<T> p = new DNode<>(data, tail, null);//数据 前节点(这时就是头结点;将尾节点赋值给头结点) 后节点(null)
//改变指针 这时尾节点 所以没有 tail.next.pre=p
tail.next=p;
//将最后一个数据赋值尾节点
this.tail=p;
}
return false;
}
/**
* 根据索引删除
* @param index
* @return
*/
@Override
public T remove(int index) {
int size=length();
T temp=null;
if(index<0||index>=size||isEmpty()){
return temp;
}
DNode<T> removeNode = this.head.next;
int j=0;
while (removeNode.next!=null&&j<index){//这时获取的删除的节点
removeNode=removeNode.next;
j++;
}
//改变指针方向,改变的是已有节点的指针方向
removeNode.pre.next=removeNode.next;
//当节点为尾节点或者只有一个节点时
if (removeNode.next==null){
removeNode.next.pre=removeNode.pre;
}
//如果是尾节点,更新尾节点
if (removeNode==tail){
this.tail=removeNode.pre;
}
return removeNode.data;
}
/**
* 根据data删除结点,无需像单向链表那样去存储要删除结点的前一个结点
* 1.头删除
* 2.中间删除
* 3.尾部删除,更新tail指向
* @param data
* @return
*/
@Override
public boolean removeAll(T data) {
boolean isRemove=false;
if(data==null||isEmpty())
return isRemove;
//注意这里的起点,如果起点为this.head,那么情况区别如同前面的根据index的删除实现
DNode<T> p=this.head.next;
//头删除/尾删除/中间删除(size>1),查找所有需要删除的结点
while (p!=null){
if(data.equals(p.data)){
if (p==this.tail){
//如果是尾结点
this.tail=p.pre;//更新未结点的指向,已经赋好值了,所以tail!=null
p.pre=null;//加速gc回收,处理删除信息
this.tail.next=null;//将next赋值为空
}else {
//如果是在中间删除,更新前继和后继指针指向
p.pre.next=p.next;
p.next.pre=p.pre;
}
isRemove=true;
p=p.next;//继续查找
}else {
p=p.next;
}
}
return isRemove;
}
/**
* 清空链表
*/
@Override
public void clear() {
this.head.next=null;
this.tail=this.head;
}
@Override
public boolean contains(T data) {
if(data==null){
return false;
}
DNode<T> p=this.head.next;
while (p!=null){
if (data.equals(p.data)){
return true;
}else {
p=p.next;
}
}
return false;
}
@Override
public String toString() {
String str="(";
DNode<T> pre = this.head.next;
while (pre!=null)
{
str += pre.data;
pre = pre.next;
if (pre!=null)
str += ", ";
}
return str+")";
}
/**
* 传入一个数组,转换成链表
* @param array
*/
public DoubleLinkedList(T[] array)
{
this();
if (array!=null && array.length>0)
{
//头结点的下一个节点赋值 新节点——>头结点
this.head.next = new DNode<T>(array[0]);
//赋值给尾节点
tail =this.head.next;
//头结点——>新节点
tail.pre=this.head;
int i=1;
while (i<array.length)
{
//新节点——>尾节点
DNode<T> tdNode = new DNode<>(array[i++]);
tail.next=tdNode;
//尾节点——>新节点
tdNode.pre=tail;
//尾节点重新赋值
tail = tail.next;
}
}
}
public static void main(String[] args){
String[] letters={"A","B","C","D","Z","E","F"};
// String[] letters={"A"};
DoubleLinkedList<String> list=new DoubleLinkedList<>(letters);
System.out.println("list.get(3)->"+list.get(3));
System.out.println("list:"+list.toString());
System.out.println("list.add(4,Y)—>"+list.add(0,"Y"));
System.out.println("list:"+list.toString());
System.out.println("list.add(Z)—>"+list.add("Z"));
System.out.println("list:"+list.toString());
System.out.println("list.contains(Z)->"+list.contains("Z"));
System.out.println("list.set(4,P)-->"+list.set(4,"P"));
System.out.println("list:"+list.toString());
System.out.println("list.remove(6)-->"+list.remove(6));
// System.out.println("list.remove(Z)->"+list.removeAll("Z"));
System.out.println("list:"+list.toString());
}
}
代码不全只是自己记录学习,借鉴:https://blog.csdn.net/javazejian/article/details/52953190;强烈推荐此大神博客。。。