package com.coding2017.week3;
import com.coding2017.basic.Iterator;
import com.coding2017.basic.List;
public class LinkedList implements List {
private Node head;
private Node tail;
private int size;
public LinkedList() {
}
public static LinkedList of(Object... objects) {
LinkedList linkedList = new LinkedList();
for (int i = 0; i < objects.length; i++) {
linkedList.add(objects[i]);
}
return linkedList;
}
public void add(Object o) {
addLast(o);
}
public void add(int index, Object o) {
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException();
}
if (index == size) {
addLast(o);
} else if (index == 0) {
addFirst(o);
} else {
Node node = new Node(o);
Node prevNode = getNode(index - 1);
Node nextNode = prevNode.next;
prevNode.next = node;
node.prev = prevNode;
nextNode.prev = node;
node.next = nextNode;
size++;
}
}
private Node getNode(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
}
Node node = head;
for (int j = 0; j < index; j++) {
node = node.next;
}
return node;
}
public Object get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
}
return getNode(index).data;
}
public Object remove(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
}
if (index == 0) {
return removeFirst();
} else if (index == size - 1) {
return removeLast();
} else {
Node node = getNode(index);
node.prev.next = node.next;
node.next.prev = node.prev;
size--;
return node.data;
}
}
public int size() {
return size;
}
public void addFirst(Object o) {
Node node = new Node(o);
if (size == 0) {
head = node;
tail = node;
} else {
head.prev = node;
node.next = head;
head = node;
}
size++;
}
public void addLast(Object o) {
if (size == 0) {
addFirst(o);
} else {
Node node = new Node(o);
tail.next = node;
node.prev = tail;
tail = node;
size++;
}
}
public Object removeFirst() {
if (size == 0) {
throw new IndexOutOfBoundsException();
}
Node node = head;
if (size == 1) {
head = null;
tail = null;
size--;
} else {
head.next.prev = null;
head = head.next;
size--;
}
return node.data;
}
public Object removeLast() {
if (size == 0) {
throw new IndexOutOfBoundsException();
}
if (size == 1) {
return removeFirst();
}
Node node = tail;
tail.prev.next = null;
tail = tail.prev;
size--;
return node.data;
}
public Iterator iterator() {
return new LinkedListIterator();
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder("[");
if (size > 0) {
builder.append(get(0));
}
for (Node node = head.next; node != null; node = node.next) {
builder.append(", ").append(node.data);
}
builder.append("]");
return builder.toString();
}
private static class Node {
private Object data;
private Node next;
private Node prev;
public Node() {
}
private Node(Object data) {
this.data = data;
}
}
private class LinkedListIterator implements Iterator {
private Node node;
public LinkedListIterator() {
this.node = LinkedList.this.head;
}
@Override
public boolean hasNext() {
return node != null;
}
@Override
public Object next() {
Node temp = node;
node = node.next;
return temp.data;
}
}
/******** 使用单向链表实现下边功能 *************/
/**
* 把该链表逆置 例如链表为 3->7->10 , 逆置后变为 10->7->3
*/
public void reverse() {
if (size == 0 || size == 1) {
return;
}
Node preNode = null;
Node curNode = head;
while (curNode != null) {
Node nextNode = curNode.next;
curNode.next = preNode;
preNode = curNode;
curNode = nextNode;
}
head = preNode;
}
/**
* 删除一个单链表的前半部分 例如:list = 2->5->7->8 , 删除以后的值为 7->8 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10
*
*/
public void removeFirstHalf() {
if (size == 0 || size == 1) {
return;
}
remove(0, size / 2);
}
/**
* 从第i个元素开始, 删除length 个元素 , 注意i从0开始
*
* @param index
* @param length
*/
public void remove(int index, int length) {
assert index >= 0 && index < size;
assert index + length <= size;
if (index == 0) {
for (int i = 0; i < length; i++) {
head = head.next;
}
} else {
Node preNode = getNode(index - 1);
preNode.next = getNode(index + length);
}
size -= length;
}
/**
* 假定当前链表和list均包含已升序排列的整数 从当前链表中取出那些list所指定的元素 例如当前链表 = 11->101->201->301->401->501->601->701 listB = 1->3->4->6
* 返回的结果应该是[101,301,401,601]
*
* @param list
*/
public int[] getElements(LinkedList list) {
int resultSize = list.size;
int[] result = new int[resultSize];
Node node = head;
Node indexNode = list.head;
int preIndex = 0;
for (int i = 0; i < resultSize; i++) {
node = forward(node, (Integer) indexNode.data - preIndex);
result[i] = (Integer) node.data;
preIndex = (Integer) indexNode.data;
indexNode = indexNode.next;
}
return result;
}
/**
* 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 从当前链表中中删除在list中出现的元素
*
* @param list
*/
public void subtract(LinkedList list) {
Node preNode = null;
Node node = head;
Node deleteNode = list.head;
while (node != null && deleteNode != null) {
int data = (Integer) node.data;
int deleteData = (Integer) deleteNode.data;
if (data == deleteData) {
if (node == head) {
head = head.next;
node = node.next;
} else {
preNode.next = node.next;
node = node.next;
}
size--;
} else if (data > deleteData) {
deleteNode = deleteNode.next;
} else {
preNode = node;
node = node.next;
}
}
}
/**
* 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同)
*/
public void removeDuplicateValues() {
if (size == 0 || size == 1) {
return;
}
Node curNode = head; // 当前节点
Node nextNode = head.next; // 查找与当前节点不同的节点
while (curNode != null) {
if (nextNode == null) {
curNode.next = null;
break;
}
if (curNode.data.equals(nextNode.data)) {
nextNode = nextNode.next;
size--;
} else {
curNode.next = nextNode;
curNode = nextNode;
nextNode = curNode.next;
}
}
}
/**
* 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素)
*
* @param min
* @param max
*/
public void removeRange(int min, int max) {
// 小于等于min的节点, 假定head也大于min
Node preNode = new Node(null);
preNode.next = head;
Node nextNode = null;
for (Node node = head; node != null; node = node.next) {
if ((Integer) node.data <= min) {
preNode = node;
} else if ((Integer) node.data >= max) {
nextNode = node;
break;
}
}
preNode.next = nextNode;
head = nextNode;
setSize();
}
/**
* 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列
*
* @param list
*/
public LinkedList intersection(LinkedList list) {
LinkedList result = new LinkedList();
Node node1 = head;
Node node2 = list.head;
while (node1 != null && node2 != null) {
int data1 = (Integer) node1.data;
int data2 = (Integer) node2.data;
if (data1 == data2) {
result.add(node1.data);
node1 = node1.next;
node2 = node2.next;
} else if (data1 < data2) {
node1 = node1.next;
} else {
node2 = node2.next;
}
}
return result;
}
private Node forward(Node node, int step) {
for (int i = 0; i < step; i++) {
node = node.next;
}
return node;
}
private void setSize() {
int size = 0;
for (Node node = head; node != null; node = node.next) {
size++;
}
this.size = size;
}
}