package com.coding.basic.linklist;
import com.coding.basic.Iterator;
import com.coding.basic.List;
import java.util.NoSuchElementException;
/**
* Created by songbao.yang on 2017/2/21.
*
*/
public class LinkedList<T extends Comparable> implements List<T> {
private Node head;
private int elementCount;
//head作为一个节点,其next的值指向List中真正的第一个节点
public LinkedList() {
head = new Node();
head.next = null;
head.data = null;
elementCount = 0;
}
public void add(T o){
Node newNode = new Node();
newNode.data = o;
newNode.next = null;
Node cursor = head;
while (cursor.next != null){
cursor = cursor.next;
}
cursor.next = newNode;
elementCount++;
}
public void add(int index , T o){
indexRangeCheck(index);
Node newNode = new Node();
newNode.data = o;
Node cursor = head;
for (int i = 0; i < index; i++) {
cursor = cursor.next; //将cursor移动到index-1节点处;
}
newNode.next = cursor.next; //将新节点指向原index处的节点
cursor.next = newNode;//将原index-1处的节点指向新节点
elementCount++;
}
private void indexRangeCheck(int index){
if (index < 0 || index >= size()){
throw new IndexOutOfBoundsException();
}
}
public T get(int index){
indexRangeCheck(index);
Node cursor = head;
for (int i = 0; i < index; i++) {
cursor = cursor.next;
}
return (T) cursor.next.data;
}
public T remove(int index){
indexRangeCheck(index);
Node cursor = head;
for (int i = 0; i < index; i++) {
cursor = cursor.next;
}
Node indexNode = cursor.next;
cursor.next = indexNode.next;
elementCount--;
return (T) indexNode;
}
public int size(){
return elementCount;
}
public void addFirst(T o){
Node node = new Node();
node.data = o;
node.next = head.next;
head.next = node;
elementCount++;
}
public void addLast(T o){
Node cursor = head;
while (cursor.next != null){
cursor = cursor.next;
}
Node newNode = new Node();
newNode.data = o;
newNode.next = null;
cursor.next = newNode;
elementCount++;
}
public T removeFirst(){
if (size() == 0){
throw new RuntimeException("no element in list");
}
Node firstNode = head.next;
head.next = head.next.next;
elementCount--;
return (T) firstNode;
}
public T removeLast(){
if (size() == 0){
throw new RuntimeException("no element in list");
}
Node cursor = head;
for (int i = 0; i < size() - 1; i++) {
cursor = cursor.next;
}
Node lastNode = cursor.next;
cursor.next = null;
elementCount--;
return (T) lastNode;
}
public Iterator iterator(){
return new Itr();
}
private class Itr implements Iterator {
private Node itrCursor = head;
public boolean hasNext() {
return itrCursor.next != null;
}
public Object next() {
if (hasNext()){
return itrCursor.next;
}
throw new NoSuchElementException();
}
}
private static class Node<T extends Comparable>{
T data;
Node next;
}
/**
* 把该链表逆置
* 例如链表为 3->7->10 , 逆置后变为 10->7->3
*/
public void reverse(){
if (elementCount <= 1){
return;
}
Node first = head.next;
Node second = head.next.next;
first.next = null;
while (second != null){
Node temp = second.next;
second.next = first;
first = second;
second = temp;
}
head.next = first;
}
/**
* 删除一个单链表的前半部分
* 例如:list = 2->5->7->8 , 删除以后的值为 7->8
* 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10
*/
public void removeFirstHalf(){
Node cousor = head.next;
for (int i = 0; i < elementCount / 2; i++) {
Node temp = cousor;
cousor = cousor.next;
temp.data = null;
temp.next = null;
}
head.next = cousor;
}
/**
* 从第i个元素开始, 删除length 个元素 , 注意i从0开始
* @param i
* @param length
*/
public void remove(int i, int length){
if (i < 0 || length < 0){
return;
}
if (i > elementCount - 1){
throw new IndexOutOfBoundsException("index i is too big");
}
Node beforei = head;
for (int j = 0; j < i; j++) {
beforei = beforei.next;
}
Node cursor = beforei.next;
for (int j = 0; j < length; j++) {
if (cursor != null){
Node temp = cursor;
cursor = cursor.next;
temp.data = null;
temp.next = null;
}else {
break;
}
}
beforei.next = cursor;
}
/**
* 假定当前链表和listB均包含已升序排列的整数
* 从当前链表中取出那些listB所指定的元素
* 例如当前链表 = 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[] result = new int[list.size()];
int i = 0;
int pre = 0;
Node cousor = head.next;
Iterator YIterator = list.iterator();
while (YIterator.hasNext()){
int index = (Integer) YIterator.next();
if (index > elementCount - 1){
break;
}
moveForwardNIndex(cousor, index - pre);
result[i++] = (Integer) cousor.data;
pre = index;
}
int[] ints = new int[result.length];
System.arraycopy(result, 0, ints, 0, result.length);
return ints;
}
private void moveForwardNIndex(Node index, int n){
for (int i = 0; i < n; i++) {
if (index == null){
break;
}
index = index.next;
}
}
/**
* 已知链表中的元素以值递增有序排列,并以单链表作存储结构。
* 从当前链表中中删除在listB中出现的元素
* @param list
*/
public void subtract(LinkedList list){
Node pre = head;
Node node = head.next;
while (node != null){
if (list.contains(node.data)){
pre.next = node.next;
node = node.next;
} else {
pre = node;
node = node.next;
}
}
}
public boolean contains(T data){
Node cursor = this.head.next;
while (cursor != null){
if (cursor.data.equals(data)){
return true;
}
}
return false;
}
/**
* 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。
* 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同)
*/
public void removeDuplicateValues(){
if (elementCount <= 1){
return;
}
Node pre = head.next;
Node node = pre.next;
while (node != null){
if (node.data.equals(pre.data)){
pre.next = node.next;
node = node.next;
} else {
pre = node;
node = node.next;
}
}
}
/**
* 已知链表中的元素以值递增有序排列,并以单链表作存储结构。
* 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素)
* @param min
* @param max
*/
//TODO 这个泛型的比较没搞明白, 为什么会出现cast的问题,不应该都是T类型吗
public void removeRange(T min, T max){
if (min.compareTo(max) > 0){
return;
}
if (size() == 0){
return;
}
Node beforeMin = head;
//泛型化
while (beforeMin.next != null && beforeMin.next.data.compareTo(min) <= 0){
beforeMin = beforeMin.next;
}
Node afterMax = beforeMin.next;
while (afterMax != null && afterMax.data.compareTo(max) < 0){
afterMax = afterMax.next;
}
beforeMin.next = afterMax;
}
/**
* 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同)
* 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列
* @param list
*/
public LinkedList intersection(LinkedList list){
if (list == null || list.size() == 0 || this.size() == 0){
return new LinkedList();
}
Node cursorA = this.head.next;
Node cursorB = list.head.next;
LinkedList<T> listC = new LinkedList<T>();
while (cursorA != null && cursorB != null){
if (cursorA.data.compareTo(cursorB.data) == 0){
listC.add((T)cursorA.data);
} else if (cursorA.data.compareTo(cursorB.data) < 0){
cursorA = cursorA.next;
} else {
cursorB = cursorB.next;
}
}
return listC;
}
public void addAfter(Node node, T o){
if (node == null){
return;
}
Node<T> newNode = new Node<T>();
newNode.data = o;
addAfter(node, newNode);
}
public void addAfter(Node node, Node newNode){
if (node == null || newNode == null){
return;
}
newNode.next = node.next;
node.next = newNode;
}
}