package com.coding.basic;
public class LinkedList implements List {
//链表头//
private Node head;
//链表尾,为了方便加上的//
private Node tail;
//链表长度,为了方便加上的//
private int size=0;
private static class Node{
Object data;
Node next=null;
}
public void add(Object o){
/*如果是空的则从头开始增加,因为要标记链表头,链表尾额外的标记下
*如果不是空的则从尾巴开始增加,因为要标记链表尾
*/
if (head==null){
addFirst(o);
tail=head;
}else{
addLast(o);
}
}
public void add(int index , Object o){
//头尾单独增加,方便维护标记//
if (index==0){
addFirst(o);
return;
}
if (index==size){
addLast(o);
return;
}
checkIndex(index);
Node current = getNode(index-1);
Node node = new Node();
node.data=o;
node.next=current.next;
current.next=node;
size++;
}
//按照下标获取节点,方便跟下标有关的增查删改//
private Node getNode(int index){
checkIndex(index);
Node current = head;
for (int i=0;i<index;i++){
current=current.next;
}
return current;
}
public Object get(int index){
return getNode(index).data;
}
public Object remove(int index){
//头尾单独处理,方便维护标记//
if (index==0){
return removeFirst();
}
if (index==size-1){
return removeLast();
}
checkIndex(index);
Node current = getNode(index-1);
Node temp = current.next;
current.next=temp.next;
size--;
return temp.data;
}
public int size(){
return size;
}
public void addFirst(Object o){
Node node = new Node();
node.data=o;
node.next=head;
head=node;//标记链表头//
size++;
}
public void addLast(Object o){
Node node = new Node();
node.data=o;
tail.next=node;
tail=node;//标记链表尾//
size++;
}
public Object removeFirst(){
Node current = head;
head=current.next;//标记链表头//
current.next=null;//切断关联//
size--;
return current.data;
}
public Object removeLast(){
Node current=getNode(size-2);
Node temp = current.next;
current.next=null;//切断关联//
tail=current;//标记链表尾//
size--;
return temp.data;
}
public Iterator iterator(){
return new Iterator();
}
private class Iterator{
Node current=head;
public boolean hasNext(){
return current!=null;
}
public Object next(){
if (current==null){
throw new IndexOutOfBoundsException("no node");
}
Node temp =current;
current=current.next;
return temp.data;
}
}
/**
* 把该链表逆置
* 例如链表为 3->7->10 , 逆置后变为 10->7->3
*/
public void reverse(){
/*两个指针,开始的时候指向头跟头后面的一个(前指针、后指针)
*循环:每次向后移动步长1,至后指针移到链表尾,size-1个节点需要移动(size-1)-1次
*先保留前指针的值temp,即当前逆序链表的头,然后再移动前、后指针
*移动后,将前指针的节点连接到逆序链表的头,开始下一次移动
*循环结束后,注意到实际重连的只有旧链表的第二个节点到倒数第个节点,需要单独处理旧链表的头尾节点
*旧链表的尾节点需要链接到逆序链表的头,旧链表的头节点的指针置空,不然会1<->2
*维护头尾标记
*/
Node current=head;
Node currentAfter=current.next;
Node temp;
for (int i=0;i<size-2;i++){
temp=current;
current=currentAfter;
currentAfter=currentAfter.next;
current.next=temp;
}
currentAfter.next=current;
tail=head;
tail.next=null;
head=currentAfter;
}
/**
* 删除一个单链表的前半部分
* 例如:list = 2->5->7->8 , 删除以后的值为 7->8
* 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10
*/
public void removeFirstHalf(){
//int截断,不会有小数//
int removeLength = size / 2;
for (int i=1;i<=removeLength;i++){
removeFirst();
}
}
/**
* 从第i个元素开始, 删除length 个元素 , 注意i从0开始
* @param i
* @param length
*/
public void remove(int i, int length){
checkIndex(i);
length=length+i-1;
if (i+length-1>size){
length=size-i;
}
//从后往前删除,防止越界//
for (int k=length;k>=i;k--){
remove(k);
}
}
/**
* 假定当前链表和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 indexLength=list.size();
int[] result=new int[indexLength];
for (int i=0;i<indexLength;i++){
int index=(int)list.get(i);
if (index>size){
result[i]=0;
}else{
result[i]=(int)list.get(index);
}
}
return result;
}
/**
* 已知链表中的元素以值递增有序排列,并以单链表作存储结构。
* 从当前链表中中删除在list中出现的元素
* @param list
*/
//注意到递增,在外层循环list的时候,保留内层循环的被比较链表的节点的下标并递增即可//
public void subtract(LinkedList list){
int startIndex=0;
Iterator iter=list.iterator();
while(iter.hasNext()){
int src =(int) iter.next();
while(startIndex<size){
if (src==(int) get(startIndex)){
remove(startIndex);
break;
}
else{
startIndex++;
}
}
}
}
/**
* 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。
* 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同)
*/
//注意到递增,保留不需要删除的节点的下标并递增即可//
public void removeDuplicateValues(){
int startIndex=1;
int scr=(int)head.data;
while(startIndex<size){
if (scr==(int) get(startIndex)){
remove(startIndex);
}else{
scr=(int) get(startIndex);
startIndex++;
}
}
}
/**
* 已知链表中的元素以值递增有序排列,并以单链表作存储结构。
* 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素)
* @param min
* @param max
*/
//这个,想用二分法但是是单链表,没想到高效的算法(网上说是B树,然而不会。。。),一个一个比较的//
public void removeRange(int min, int max){
Node current=head;
Node temp=head;
boolean isHeadNoed=true;
while(current!=null){
if ((int)current.data<min || (int)current.data>max){
if (isHeadNoed){
current=current.next;
removeFirst();
}else{
temp.next=current.next;
current=current.next;
size--;
}
}else{
temp=current;
current=current.next;
isHeadNoed=false;
}
}
}
/**
* 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同)
* 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列
* @param list
*/
//注意到递增,保留内循环下标位置递增即可//
public LinkedList intersection( LinkedList list){
LinkedList result = new LinkedList();
int startIndex = 0;
for (Iterator iter = list.iterator();iter.hasNext();){
int src = (int) iter.next();
while (startIndex<size){
Object tar = get(startIndex);
if (src == (int) tar){
result.add(tar);
break;
}else{
startIndex++;
}
}
}
return result;
}
private void checkIndex(int index){
if (index<0 || index >=size){
throw new IndexOutOfBoundsException("get " + index+" in "+size);
}
}
public String toString(){
StringBuilder sb = new StringBuilder();
Node current = head;
for (int i=0;i<size;i++){
sb.append(current.data);
if (current.next!=null){
sb.append("->");
}
current=current.next;
}
return sb.toString();
}
}