package com.coding.basic;
import java.util.NoSuchElementException;
public class LinkedList implements List {
private Node head;
public void add(Object o){
Node pNewNode = new Node();
pNewNode.data = o;
Node pNode = head;
if (head == null) {
head = pNewNode;
return;
}
while (pNode.next != null) {
pNode = pNode.next;
}
pNode.next = pNewNode;
}
public void add(int index , Object o){
if (index < 0 || index > size()) {
throw new IndexOutOfBoundsException();
}
Node pNewNode = new Node();
pNewNode.data = o;
if (index == 0) {
pNewNode.next = head;
head = pNewNode;
return;
}
Node pNode = head;
while (--index > 0) {
pNode = pNode.next;
}
pNewNode.next = pNode.next;
pNode.next = pNewNode;
}
public Object get(int index){
ensureBounds(index);
Node pNode = head;
while (index-- > 0) {
pNode = pNode.next;
}
return pNode.data;
}
public Object remove(int index){
ensureBounds(index);
Node pNode = head;
if (index == 0) {
head = head.next;
return pNode.data;
}
while (--index > 0) {
pNode = pNode.next;
}
Node pTargetNode = pNode.next;
pNode.next = pTargetNode.next;
return pTargetNode.data;
}
private void ensureBounds(int index) {
if (index < 0 || index >= size()) {
throw new IndexOutOfBoundsException();
}
}
public int size(){
Node pNode = head;
int num = 0;
while (pNode != null) {
pNode = pNode.next;
num++;
}
return num;
}
public void addFirst(Object o){
Node pNewNode = new Node();
pNewNode.data = o;
pNewNode.next = head;
head = pNewNode;
}
public void addLast(Object o){
add(o);
}
public Object removeFirst(){
if (head == null) {
throw new NoSuchElementException();
}
return remove(0);
}
public Object removeLast(){
if (head == null) {
throw new NoSuchElementException();
}
Node pNode = head;
Node pPrevNode = null;
while (pNode.next != null) {
pPrevNode = pNode;
pNode = pNode.next;
}
if (pPrevNode != null) {
pPrevNode.next = pNode.next;
}
else {
head = null;
}
return pNode.data;
}
public Iterator iterator(){
return new Itr();
}
private class Itr implements Iterator {
int index = 0;
Node pCurr = head;
Node pPrevPrev = null;
boolean hasCalledRemove = false;
@Override
public boolean hasNext() {
return (pCurr != null);
}
@Override
public Object next() {
if (pCurr == null) {
throw new NoSuchElementException();
}
Object retOb = pCurr.data;
pCurr = pCurr.next;
index++;
if (index == 2) {
pPrevPrev = head;
} else if (index > 2 && !hasCalledRemove) {
pPrevPrev = pPrevPrev.next;
}
hasCalledRemove = false;
return retOb;
}
@Override
public void remove() {
if (hasCalledRemove) {
throw new IllegalStateException();
}
hasCalledRemove = true;
if (index == 1) {
head = head.next;
index--;
} else if (pPrevPrev != null) {
pPrevPrev.next = pCurr;
index--;
} else {
throw new IllegalStateException();
}
}
}
private static class Node{
Object data;
Node next;
}
/**
* 把该链表逆置
* 例如链表为 3->7->10 , 逆置后变为 10->7->3
*/
public void reverse(){
if (head == null) {
return;
}
Node pNode1 = head, pNode2 = head.next, tmpNode;
// 1. 断开head和后面节点的连接
head.next = null;
// 2. 每一步的初始状况若为
// <--pNode1 pNode2-->pNode3... 其中pNode2不可为null, pNode3可为null
// 则需将其转为
// <--pNode1<--pNode2 pNode3...
while (pNode2 != null) {
tmpNode = pNode2.next;
pNode2.next = pNode1;
pNode1 = pNode2;
pNode2 = tmpNode;
}
// 3. 将最后一个非空节点设为head
head = pNode1;
}
/**
* 删除一个单链表的前半部分
* 例如:list = 2->5->7->8 , 删除以后的值为 7->8
* 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10
*/
public void removeFirstHalf(){
int len = size() / 2;
while (len-- > 0) {
head = head.next;
}
}
/**
* 从第i个元素开始, 删除length 个元素 , 注意i从0开始
* @param i
* @param length
*/
public void remove(int i, int length){
ensureBounds(i);
Node pNode1 = head, pNode2;
// 1. 找到第i个节点pNode2,若i不为0,找到第i-1个节点pNode1, 否则将head设为null提示其需要移动到新的节点
if (i == 0) {
pNode2 = head;
head = null;
} else {
while (--i > 0) {
pNode1 = pNode1.next;
}
pNode2 = pNode1.next;
}
// 2. pNode2从当前位置开始,跳跃length个元素
while (length-- > 0 && pNode2 != null) {
pNode2 = pNode2.next;
}
// 3. 若需要移动head节点,则把当前pNode设为head;否则删掉pNode1和pNode2之间的所有节点
if (head == null) {
head = pNode2;
} else {
pNode1.next = pNode2;
}
}
/**
* 假定当前链表和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){
if (list == null) {
return new int[0];
}
int size = list.size();
int index;
int[] elements = new int[size];
for (int i = 0; i < size; i++) {
index = ((Integer)list.get(i)).intValue();
elements[i] = ((Integer)get(index)).intValue();
}
return elements;
}
/**
* 已知链表中的元素以值递增有序排列,并以单链表作存储结构。
* 从当前链表中中删除在list中出现的元素
* @param list
*/
// 将list递增排序,从当前链表中找到与list的交集并删除
public void subtract(LinkedList list){
if (list == null) {
return;
}
list = binaryTreeSort(list);
Iterator listItr = list.iterator();
Iterator mainItr = iterator();
intersectionIteration(new intersectionIterationCallback(){
@Override
public void onElementFound(Object element) {
mainItr.remove();
}
}, listItr, mainItr);
}
/**
* 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。
* 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同)
*/
public void removeDuplicateValues(){
Iterator itr = iterator();
Integer lastInt = null, currInt;
while (itr.hasNext()) {
currInt = (Integer)itr.next();
if (lastInt != null && lastInt.intValue() == currInt.intValue()) {
itr.remove();
}
lastInt = currInt;
}
}
/**
* 已知链表中的元素以值递增有序排列,并以单链表作存储结构。
* 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素)
* @param min
* @param max
*/
public void removeRange(int min, int max){
Node pNode = head, pNodeMark = null;
// 1. 从head开始遍历,找到第一个大于min的节点,记录之前的节点
while (pNode != null && (Integer)pNode.data <= min) {
pNodeMark = pNode;
pNode = pNode.next;
}
// 2. 继续遍历,找到第一个不小于max的节点
while (pNode != null && (Integer)pNode.data < max) {
pNode = pNode.next;
}
// 3. 删除第2步遍历的所有节点
if (pNodeMark == null) {
head = pNode;
} else {
pNodeMark.next = pNode;
}
}
/**
* 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同)
* 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列
* @param list
*/
public LinkedList intersection( LinkedList list){
LinkedList newList = new LinkedList();
if (list == null) {
return newList;
}
Iterator listItr = list.iterator();
Iterator mainItr = iterator();
// 找到所有交集元素,并将其添加到新到链表
intersectionIteration(new intersectionIterationCallback(){
@Override
public void onElementFound(Object element) {
newList.add(element);
}
}, listItr, mainItr);
return newList;
}
// 将用二叉树排序生成新的递增链表,生成的链表不会包含值相同的多余元素
public LinkedList binaryTreeSort(LinkedList list) {
if (list == null) {
return null;
}
Iterator listItr = list.iterator();
BinaryTreeNode root = new BinaryTreeNode();
while (listItr.hasNext()) {
root.insert(listItr.next());
}
LinkedList sortedList = new LinkedList();
addNodeToLinkedList(sortedList, root);
return sortedList;
}
// 用递归的方式将二叉树中的元素加入链表中,使链表为递增排列
private void addNodeToLinkedList(LinkedList list, BinaryTreeNode node) {
if (node == null || node.getData() == null) {
return;
}
addNodeToLinkedList(list, node.getRight());
list.addFirst(node.getData());
addNodeToLinkedList(list, node.getLeft());
}
// 寻找交集时的返回接口,其中包含了找到元素时的返回函数
private interface intersectionIterationCallback {
void onElementFound(Object element);
}
// 按递增顺序寻找当前链表中所有在list链表中出现的元素(数值相同即视作完全等同),找到即呼叫一次返回函数
// 需要提供实例化的返回接口,list链表的迭代器和当前列表的迭代器
// 要求:list链表和当前链表必须递增排列
private void intersectionIteration(intersectionIterationCallback callback, Iterator listItr, Iterator mainItr) {
if (!listItr.hasNext() || !mainItr.hasNext()) {
return;
}
Integer listValue = (Integer)listItr.next();
Integer mainValue = (Integer)mainItr.next();
while (listItr.hasNext() || mainItr.hasNext()) {
if (listValue < mainValue) {
if (!listItr.hasNext()) {
break;
}
listValue = (Integer)listItr.next();
} else if (listValue > mainValue) {
if (!mainItr.hasNext()) {
break;
}
mainValue = (Integer)mainItr.next();
} else {
callback.onElementFound(mainValue);
mainValue = (Integer)mainItr.next();
// substract方程中,当前链表的值可能会相同,所以此时不将list移向下一个节点
}
}
// while循环退出前最后得到的listValue或mainValue并未参与比较
if (listValue.intValue() == mainValue.intValue()) {
callback.onElementFound(mainValue);
}
}
}