All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.andyshao.data.structure.DoubleLinked Maven / Gradle / Ivy

The newest version!
package com.github.andyshao.data.structure;

import java.io.Serial;
import java.io.Serializable;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.Objects;
import java.util.function.Function;

/**
 * 
 * Title:Double Linked interface
* Descript:
* Copyright: Copryright(c) Feb 9, 2015
* Encoding:UNIX UTF-8 * * @author Andy.Shao * * @param data */ public interface DoubleLinked extends Linked>, Serializable { /** * Double linked element * @param data type */ public interface DoubleLinkedElmt extends Linked.LinkedElmt>, Serializable { /** * Get default {@link DoubleLinkedElmt} * @param data data * @return {@link DoubleLinkedElmt} * @param data type */ public static DoubleLinkedElmt defaultElmt(DATA data) { DoubleLinkedElmt result = new DoubleLinkedElmt() { @Serial private static final long serialVersionUID = -107307947887970784L; private DATA data; private DoubleLinkedElmt next; private DoubleLinkedElmt prev; @Override public DATA data() { return this.data; } @SuppressWarnings("unchecked") @Override public boolean equals(Object obj) { DoubleLinkedElmt that; if (obj instanceof DoubleLinkedElmt) { that = (DoubleLinkedElmt) obj; return Objects.equals(this.data() , that.data()) && Objects.equals(this.next() , that.next()) && Objects.equals(this.getPrev() , that.getPrev()); } else return false; } @Override public DoubleLinkedElmt getPrev() { return this.prev; } @Override public int hashCode() { return Objects.hash(this.data() , this.getPrev() , this.next()); } @Override public DoubleLinkedElmt next() { return this.next; } @Override public void setData(DATA data) { this.data = data; } @Override public void setNext(DoubleLinkedElmt next) { this.next = next; } @Override public void setPrev(DoubleLinkedElmt prev) { this.prev = prev; } }; result.setData(data); return result; } /** * Get previous {@link DoubleLinkedElmt} * @return {@link DoubleLinkedElmt} */ public DoubleLinkedElmt getPrev(); /** * Set previous {@link DoubleLinkedElmt} * @param prev {@link DoubleLinkedElmt} */ public void setPrev(DoubleLinkedElmt prev); } /** * Default {@link DoubleLinked} * @param data type */ public class MyDoubleLinked implements DoubleLinked { @Serial private static final long serialVersionUID = 8162911921677856435L; /**action count*/ private long actionCount = 0; /**element factory*/ private final Function> elmtFactory; /**head of the elements*/ private DoubleLinked.DoubleLinkedElmt head; /**size*/ private int size; /**tail of the elements*/ private DoubleLinked.DoubleLinkedElmt tail; /** * Build {@link MyDoubleLinked} * @param elmtFactory {@link DoubleLinkedElmt} factory */ public MyDoubleLinked(Function> elmtFactory) { this.elmtFactory = elmtFactory; } @Override public void clear() { do this.remove(this.head); while (this.size != 0); } @SuppressWarnings("unchecked") @Override public boolean equals(Object obj) { DoubleLinked that; if (obj instanceof DoubleLinked) { that = (DoubleLinked) obj; return this.size == that.size() && Objects.equals(this.head() , that.head()) && Objects.equals(this.tail() , that.tail()); } else return false; } @Override public Function> getElmtFactory() { return this.elmtFactory; } @Override public int hashCode() { return Objects.hash(this.head , this.size , this.tail); } @Override public DoubleLinked.DoubleLinkedElmt head() { return this.head; } @Override public void insNext(DoubleLinked.DoubleLinkedElmt element , final DATA data) { //Do not allow a NULL element unless the list is empty. if (element == null && this.size() != 0) throw new LinkedOperationException("Do not allow a NULL element unless the list is empty."); DoubleLinked.DoubleLinkedElmt new_element = this.getElmtFactory().apply(data); if (this.size() == 0) { //Handle insertion when the list is empty. this.head = new_element; this.head.setPrev(null); this.head.setNext(null); this.tail = new_element; } else { //Handle insertion when the list is not empty. new_element.setNext(element.next()); new_element.setPrev(element); if (element.next() == null) this.tail = new_element; else element.next().setPrev(new_element); element.setNext(new_element); } //Adjust the size of the list to account for the inserted element. this.size++; this.actionCount++; } @Override public void insPrev(DoubleLinked.DoubleLinkedElmt element , final DATA data) { //Do not allowed a NULL element unless the list is empty. if (element == null && this.size() != 0) throw new LinkedOperationException("Do not allowed a NULL element unless the list is empty."); DoubleLinked.DoubleLinkedElmt new_element = this.getElmtFactory().apply(data); if (this.size() == 0) { //Handle insertion when the list is empty. this.head = new_element; this.head.setPrev(null); this.head.setNext(null); this.tail = new_element; } else { //Handle insertion when the list is not empty. new_element.setNext(element); new_element.setPrev(element.getPrev()); if (element.getPrev() == null) this.head = new_element; else element.getPrev().setNext(new_element); element.setPrev(new_element); } //Adjust the size of list to accoutn for the element. this.size++; this.actionCount++; } @Override public Iterator iterator() { return new Iterator() { private DoubleLinked.DoubleLinkedElmt index = MyDoubleLinked.this.head; private final long myActioncount = MyDoubleLinked.this.actionCount; @Override public boolean hasNext() { if (this.myActioncount != MyDoubleLinked.this.actionCount) throw new ConcurrentModificationException(); return this.index != null; } @Override public DATA next() { DoubleLinked.DoubleLinkedElmt result = this.index; this.index = this.index.next(); return result.data(); } }; } @Override public DATA remNext(DoubleLinkedElmt element) { DoubleLinkedElmt old_element = this.getElmtFactory().apply(null); DATA data = null; if (this.size() == 0) throw new LinkedOperationException("Do not allow removal from an empty list."); //Remove the element from the list. if (element == null) { //Handle removal from the head of the list. data = this.head.data(); old_element = this.head; this.head = this.head.next(); if (this.size() == 1) this.tail = null; } else { if (element.next() == null) return null; data = element.next().data(); old_element = element.next(); element.setNext(element.next().next()); if (element.next() == null) this.tail = element; } old_element.free(); //Adjust the size of the list of account for the removed element. this.size--; this.actionCount++; return data; } @Override public DATA remove(DoubleLinked.DoubleLinkedElmt element) { DATA data = null; //Do not allow a NULL element or removal from an empty list. if (element == null || this.size() == 0) throw new LinkedOperationException("Do not allow a NULL element or removal from an empty list."); //Remove the element from the list. data = element.data(); if (element.equals(this.head)) { //Handle removal from the head of the list. this.head = element.next(); if (this.head == null) this.tail = null; else element.next().setPrev(null); } //Free the storage allocated by the abstract datatype. element.free(); //Adjust the size of the list to account for the removed element. this.size--; this.actionCount++; return data; } @Override public int size() { return this.size; } @Override public DoubleLinked.DoubleLinkedElmt tail() { return this.tail; } } /** * Get default {@link DoubleLinked} * @return {@link DoubleLinked} * @param data type */ public static DoubleLinked defaultDoubleLinked() { return DoubleLinked.defaultDoubleLinked(DoubleLinkedElmt::defaultElmt); } /** * Get default {@link DoubleLinked} * @param elmtFactory {@link DoubleLinkedElmt} factory * @return {@link DoubleLinked} * @param data type */ public static DoubleLinked defaultDoubleLinked(Function> elmtFactory) { return new MyDoubleLinked<>(elmtFactory); } /** * Insert in the previous position of the {@link DoubleLinkedElmt} * @param element {@link DoubleLinkedElmt} * @param data the data */ public void insPrev(DoubleLinkedElmt element , final D data); /** * Remove the {@link DoubleLinkedElmt} * @param element {@link DoubleLinkedElmt} * @return the data which is omitted */ public D remove(DoubleLinkedElmt element); }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy