单项链表:顾名思义单项的,只能从首个元素向下查找,第一个元素存储着第二个元素的地址,以此类推...
package org.java.pro.link;
import java.util.NoSuchElementException;
public class SinglyLinkedList<E> {
private Node<E> first; //单链表的头结点
private Node<E> last; //单链表的最后一个节点
private int size;
public SinglyLinkedList(){
}
public SinglyLinkedList(SinglyLinkedList c){
this();
addAll(c);
}
static class Node<E>{
E data; //数据域
Node<E> next; //指针域
public Node(E data){
this.data = data;
}
}
/**
* 返回单链表的长度
* @return
*/
public int size(){
return size;
}
/**
* 在单链表尾部添加一个元素节点
* @param element
*/
public void add(E element){
Node<E> node = new Node<E>(element);
Node<E> l = last;
if(l == null){ //表明之前没有节点
first = node;
}else{
l.next = node;
}
last = node;
size++;
}
/**
* 删除节点
*/
public E remove(){
return removeFirst();
}
/**
* 删除第一个节点
* @return
*/
private E removeFirst(){
Node<E> f = first;
if(f == null){
throw new NoSuchElementException();
}
return unlinkFirst(f);
}
/**
* 删除第一个节点
* @param node
* @return
*/
private E unlinkFirst(Node<E> node) {
E element = node.data;
Node<E> next = node.next;
node.data = null;
node.next = null;
first = next;
if(next == null){
last = null;
}
size--;
return element;
}
/**
* 在链表尾部添加一个集合
* @param list
* @return
*/
public boolean addAll(SinglyLinkedList<E> list){
return addAll(size,list);
}
/**
* 返回单链表的Object[]数组
* @return
*/
public Object[] toArray() {
Object[] result = new Object[size];
int i = 0;
Node<E> e = first;
while(e!=null){
result[i++] = e.data;
e = e.next;
}
return result;
}
/**
* 在指定位置添加集合
* @param index
* @param list
* @return
*/
private boolean addAll(int index,SinglyLinkedList<E> list){
if(index<0 || index > size){
throw new IndexOutOfBoundsException("Index: "+index+ ", Size: "+size);
}
Object[] a = list.toArray();
int numNew = a.length;
if(numNew == 0){
return false;
}
for(Object o : a){
E e = (E)o;
Node<E> newNode = new Node<>(e);
if(last==null){
first = newNode;
}else{
last.next = newNode;
}
last = newNode;
}
size += numNew;
return true;
}
/**
* 根据传入的Index查找节点
* @param index
* @return
*/
private Node<E> node(int index){
Node<E> x = first;
for(int i=0;i<index;i++){
x = x.next;
}
return x;
}
public E get(int index){
if(index<0||index>=size){
throw new IndexOutOfBoundsException("Index:"+index);
}
return node(index).data;
}
}
双向链表,即除了首元素和尾元素外,每个元素存储着上个元素的地址和下个元素的地址,首元素存储着第二个元素的地址,尾元素存储着倒数第二个元素的地址,这样想查某个元素可以从尾部开始查询也可以从首元素开始查询。代表有LinkedList:
package org.java.pro.link;
import java.util.Collection;
import java.util.NoSuchElementException;
public class DoubeLinkedList<E> {
transient int size = 0; //链表中的节点个数
transient Node<E> first; //定义链表头结点
transient Node<E> last; //定义最后一个节点
private static class Node<E> {
// E item;
E element;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
// this.item = element;
this.element = element;
this.next = next; //指向下一个节点
this.prev = prev; //指向上一个节点
}
}
public DoubeLinkedList() {
}
public DoubeLinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
/**
* 添加元素
* @param e
* @return
*/
public boolean add(E e){
linkLast(e);
return true;
}
/**
* 在指定的位置往集合中添加元素e
* @param index
* @param e
*/
public void add(int index,E e){
checkPositionIndex(index);
if(index == size){
linkLast(e);
}else{
linkBefore(e,node(index));
}
}
/**
* 添加元素作为第一个节点
* @param e
*/
public void addFirst(E e){
linkFirst(e);
}
/**
* 添加元素作为最后一个节点
* @param e
*/
public void addLast(E e){
linkLast(e);
}
/**
* 在链表头部添加元素e,并将元素e作为第一个元素
* @param e
*/
private void linkFirst(E e){
Node<E> f = first;
Node<E> newNode = new Node<>(null,e,f);
first = newNode;
if(f==null){
last = newNode;
}else{
f.prev = newNode;
}
size++;
}
/**
* 在链表尾部添加元素e,并将e作为最后一个元素
* @param e
*/
private void linkLast(E e){
Node<E> l = last;
Node newNode = new Node(l,e,null);
if(l == null){
first = newNode;
}else{
l.next = newNode;
newNode.prev = l;
}
last = newNode;
size++;
}
/**
* 在非空节点succ之前插入元素e
* @param e
* @param succ
*/
private void linkBefore(E e,Node<E> succ){
Node<E> pred = succ.prev;
Node<E> newNode = new Node<>(pred,e,succ);
if(pred == null){
first = newNode;
}else{
pred.next = newNode;
}
succ.prev = newNode;
size++;
}
/**
* 将集合c追加到LinkedList中
* @param c
* @return
*/
public boolean addAll(Collection<? extends E> c){
return addAll(size,c);
}
/**
* 将集合c添加到LinkedList的指定位置
* @param index
* @param c
* @return
*/
public boolean addAll(int index,Collection<? extends E> c){
checkPositionIndex(index);
Object[] a = c.toArray();
int numNew = a.length;
if(numNew==0){
return false;
}
Node<E> pred,succ; //设置当前要插入节点的前后节点
if(index==size){
succ = null;
pred = last;
}else{
succ = node(index);
pred = succ.prev;
}
/****插入开始***/
for(Object o : a){
E e = (E)o;
Node<E> newNode = new Node<>(pred,e,null);
if(pred==null){
first = newNode;
}else{
pred.next = newNode;
}
//此时把下一个要插入的节点的上一个节点变成刚刚插入的节点
pred = newNode;
}
/****插入完成***/
//设置前后节点的关系
if(succ == null){
last = pred;
}else{
pred.next = succ;
succ.prev = pred;
}
size += numNew;
return true;
}
/**
* 删除元素,默认删除第一个,并返回
* @return
*/
public E remove(){
return removeFirst();
}
/**
* 删除集合中指定位置的元素
* @param index
* @return
*/
public E remove(int index){
checkElementIndex(index);
return unlink(node(index));
}
/**
* 在集合中删除指定的对象
* @param o
* @return
*/
public boolean remove(Object o){
if(o == null){
for(Node<E> x=first;x!=null;x=x.next){
if(x.element == null){
unlink(x);
return true;
}
}
}else{
for(Node<E> x=first;x!=null;x=x.next){
if(x.element.equals(o)){
unlink(x);
return true;
}
}
}
return false;
}
/**
* 删除链表的第一个元素并返回
* @return
*/
public E removeFirst(){
Node<E> f = first;
if(f == null){
throw new NoSuchElementException();
}
return unlinkFirst(f);
}
/**
* 删除链表的最后一个元素,并返回
* @return
*/
public E removeLast(){
Node<E> l = last;
if(l == null){
throw new NoSuchElementException();
}
return unlinkLast(l);
}
/**
* 清空链表 循环遍历全部置为null
*/
public void clear(){
for(Node<E> x=first;x!=null;x=x.next){
x.element =null;
x.prev = null;
x.next = null;
x = null;
}
first = last = null;
size = 0;
}
/**
* 删除一个非空节点x,并返回
* @param x
* @return
*/
private E unlink(Node<E> x){
E element = x.element;
Node<E> pred = x.prev;
Node<E> succ = x.next;
if(pred == null){
first = succ;
}else{
pred.next = succ;
x.prev = null;
}
if(succ == null){
last = pred;
}else{
succ.prev = pred;
x.next = null;
}
x.element = null;
size--;
return element;
}
/**
* 删除不为空的第一个节点
* @param f
*/
private E unlinkFirst(Node<E> f){
E element = f.element;
Node<E> succ = f.next;
f.element = null; //help gc
f.next = null;
first = succ;
if(succ == null){
last = null;
}else{
succ.prev = null;
}
size--;
return element;
}
/**
* 删除不为空的最后一个节点
* @param l
* @return
*/
private E unlinkLast(Node<E> l){
E element = l.element;
Node<E> pred = l.prev;
l.element = null;
l.prev = null;
last = pred;
if(pred == null){
first = null;
}else{
pred.next = null;
}
size--;
return element;
}
/**
* 修改在链表中指定位置的元素
* @param index
* @param e
* @return
*/
public E set(int index,E e){
checkElementIndex(index);
Node<E> oldNode = node(index);
E oldVal = oldNode.element;
oldNode.element = e;
return oldVal;
}
/**
* 根据index获取集合中的指定的元素
* @param index
* @return
*/
public E get(int index){
checkElementIndex(index);
return node(index).element;
}
/**
* 获取第一个节点上的元素
* @return
*/
public E getFirst(){
Node<E> f = first;
if(f == null){
throw new NoSuchElementException();
}
return f.element;
}
/**
* 获取最后一个节点的元素
* @return
*/
public E getLast(){
Node<E> l = last;
if(l == null){
throw new NoSuchElementException();
}
return l.element;
}
/**
* 根据index位置获取节点
* 利用双向链表的特点提高查找效率
* @param index
* @return
*/
private Node<E> node(int index){
if(index < (size>>1)){ //说明要查找的节点在前半部分
Node<E> x = first;
for(int i=0;i<index;i++){
x = x.next;
}
return x;
}else{ //说明要查找的节点在前半部分
Node<E> x = last;
for(int i=size-1;i>index;i--){
x = x.prev;
}
return x;
}
}
/**
* 返回LinkedList的大小
* @return
*/
public int size(){
return size;
}
/**
* 判断集合是否为空
* @return
*/
public boolean isEmpty(){
return size == 0;
}
/**
* 判断链表集合中是否包含此对象
* @param o
* @return
*/
public boolean contains(Object o){
return indexOf(o) >= 0;
}
/**
* 获取对象o在链表集合中的索引位置
* @param o
* @return
*/
public int indexOf(Object o){
int index = 0;
if(o == null){
for(Node<E> x=first;x!=null;x=x.next){
if(x.element == null){
return index;
}
index++;
}
}else{
for(Node<E> x=first;x!=null;x=x.next){
if(x.element.equals(o)){
return index;
}
index++;
}
}
return -1;
}
/**
* 返回此对象在链表中最后出现的位置
* @param o
* @return
*/
public int lastIndexOf(Object o){
int index = size-1;
if(o == null){
for(Node<E> x=last;x!=null;x=x.prev){
if(x.element == null){
return index;
}
index--;
}
}else{
for(Node<E> x=last;x!=null;x=x.prev){
if(x.element.equals(o)){
return index;
}
index--;
}
}
return -1;
}
/**
* 添加元素的时候检查索引位置
* @param index
*/
private void checkPositionIndex(int index){
if(index<0 || index>size) {
throw new IndexOutOfBoundsException("Index:" + index + ",Size:" + size);
}
}
/**
* 在删除和获取元素时判断检查下标位置
* @param index
*/
private void checkElementIndex(int index){
if(index<0 || index>=size) {
throw new IndexOutOfBoundsException("Index:" + index + ",Size:" + size);
}
}
/**
* 返回LinkedList的Object数组
* @return
*/
public Object[] toArray(){
Object[] o = new Object[size];
int i=0;
for(Node<E> x=first;x!=null;x=x.next){
o[i++] = x.element;
}
return o;
}
/*** LinkedList实现了Deque<E>接口,Deque<E>接口对Queue<E>接口进行了扩展</>
* </> LinkedList作为队列使用
* 一般用LinkedList作为队列使用较多,使用栈的时候最好还是使用Stack<E>这个类
* </>*****/
/**
* 往队列尾部添加元素
* @param e
* @return
*/
public boolean offer(E e){
return add(e);
}
/**
* 从队列头部取元素,并删除
* @return
*/
public E poll(){
Node<E> f = first;
if(f == null){
return null;
}
return unlinkFirst(f);
}
/**
* 从队列头部读取元素,但是不删除
* @return
*/
public E peek(){
Node<E> f = first;
if(f == null){
return null;
}
return f.element;
}
public boolean offerFrist(E e){
addFirst(e);
return true;
}
public boolean offerLast(E e){
addLast(e);
return true;
}
public E pollFirst(){
Node<E> f = first;
if(f == null){
return null;
}
return unlinkFirst(f);
}
public E pollLast(){
Node<E> f = first;
if(f == null){
return null;
}
return unlinkLast(f);
}
public E peekFirst(){
Node<E> f = first;
if(f == null){
return null;
}
return f.element;
}
public E peekLast(){
Node<E> l = last;
if(l == null){
return null;
}
return l.element;
}
/*** LinkedList还可以当成是栈来使用 *****/
/**
* 往栈顶添加元素,就是在链表前面添加元素作为第一个节点
* @param e
*/
public void push(E e){
addFirst(e);
}
/**
* 往栈顶取元素并删除,即删除链表前面删除元素,这样在就满足了栈的先进后出的原则
* 还有个不删除的就是和peek()方法一样
* @return
*/
public E pop(){
return removeFirst();
}
}
单元测试类:
package org.java.pro .link;
public class TestLinkedList {
public static void main(String[] args) {
DoubeLinkedList<Integer> dList = new DoubeLinkedList<>();
dList.add(30);
dList.add(50);
dList.add(45);
for (int i = 0; i < dList.size; i++) {
System.out.println(dList.get(i));
}
System.out.println("--------------------------------------");
SinglyLinkedList<String> sList = new SinglyLinkedList<>();
sList.add("zhansan");
sList.add("lisi");
sList.add("wangwu");
for (int i = 0; i < sList.size(); i++) {
System.out.println(sList.get(i));
}
}
}