目录
完整代码:
package list;
import java.util.Iterator;
//不带头结点的单链表
@SuppressWarnings("all")
public class CLinkedList<T> implements Ilist<T>, Iterable<T>, Cloneable {
/**
* Node 内部类
*
* @param <T>
*/
private static class Node<T> {
// 注意和Itr类的比较,通过这个例子,应该能明白静态嵌套类和内部类的使用场合
T data;
Node<T> next;
Node(T data, Node<T> next) {
this.data = data;
this.next = next;
}
public String toString() {//测试后面的tail有没有弄对
return String.valueOf(data);
}//测试用
}
private Node<T> head;
private int size;
public CLinkedList() {
// head = null;
// size = 0;
}
/**
* isEmpty
*
* @return size == 0
*/
public boolean isEmpty() {
return size == 0;
}
/**
* size
*
* @return size
*/
public int size() {
return size;
}
/**
* indexOf x不能为null
*
* @param x
* @return
*/
public int indexOf(T x) {
int index = 0;
for (Node<T> p = head; p != null; p = p.next) {
if (x.equals(p.data))
return index;
++index;
}
return -1;
}
/**
* indexOf1 数据就可以是null,x也可以是null
*
* @param x
* @return
*/
public int indexOf1(T x) {
if (x == null) {
int index = 0;
for (Node<T> p = head; p != null; p = p.next) {
if (p.data == null)
return index;
++index;
}
} else {
int index = 0;
for (Node<T> p = head; p != null; p = p.next) {
if (x.equals(p.data))
return index;
++index;
}
}
return -1;
}
// 可以这样写,但是,java类库用的前面的indexOf的写法,使用引用变量控制循环,不要用下面的写法
public int indexOf2(T x) {
Node<T> p = head;
for (int index = 0; index < size; ++index) {
if (x.equals(p.data))
return index;
p = p.next;
}
return -1;
}
// 可以用while,但是,看起来没有for容易理解,不要使用
public int indexOf3(T x) {
Node<T> p = head;
int index = 0;
while (p != null) {
if (x.equals(p.data))
return index;
p = p.next;
++index;
}
return -1;
}
/**
* 将索引号的合法性检查抽出作为方法
*
* @param index
*/
private void rangCheckForAdd(int index) {// add用
if (index < 0 || index > size)
throw new IndexOutOfBoundsException(String.valueOf(index));
}
private void rangeCheck(int index) {// 其它方法用
if (index < 0 || index > size - 1)
throw new IndexOutOfBoundsException(String.valueOf(index));
}
/**
* get
*
* @param index
* @return
*/
public T get(int index) {
rangeCheck(index);
Node<T> p = head;
for (int i = 0; i < index; i++) // 找到结点index
p = p.next;
return p.data;
}
/**
* add
*
* @param index
* @param x
*/
public void add(int index, T x) {
rangCheckForAdd(index);
if (index == 0) {// 空表,及插入位置0
head = new Node<>(x, head);
} else {
Node<T> p = head;
for (int i = 0; i < index - 1; i++) // 找到index的前驱
p = p.next;
p.next = new Node<>(x, p.next);
}
++size;
}
/**
* remove
*
* @param index
* @return
*/
public T remove(int index) {
rangeCheck(index);
Node<T> p = head;
if (index == 0) {// 肯定不为空
head = head.next;
} else {// 至少有2个结点
// 找到index的前驱
for (int i = 0; i < index - 1; i++)
p = p.next;
Node<T> q = p;
p = p.next;
q.next = p.next;
}
// p引用待删除结点
T value = p.data;
p.data = null;// 帮助GC
p.next = null;
--size;
return value;
}
/**
* reverse
*/
public void reverse() {//逆序
if (head == null || head.next == null) return;
Node<T> p = head.next;//先指到第2个节点
head.next = null;//把第一个节点断开
while (p != null) {
Node<T> q = p.next;//后移
//将p插入头结点之后
p.next = head;
head = p;
p = q;//继续访问下一个元素
}
}
/**
* removeRange
*
* @param from
* @param to
*/
public void removeRange(int from, int to) {
rangeCheck(from);
rangeCheck(to);//检查index
Node<T> from_h = head;
Node<T> to_b = head;
Node<T> p = head;//帮助GC的指针
if (from == 0) {//from在开头的情况
for (int i = 0; i < to + 1; i++) {
p = to_b.next;
to_b = null;
to_b = p;
}
head = to_b;
} else {//一般情况
for (int i = 0; i < to + 1; i++) {
if (i < from - 1) {
from_h = from_h.next;
}
p = to_b.next;
to_b = null;
to_b = p;
}
from_h.next = to_b;
}
size = size - (to - from + 1);//更改size
}
/**
* lastIndex
*
* @param x
* @return
*/
public int lastIndex(T x) {
Node<T> p = head;
int index = -1;
int i = 0;
while (p != null) {
if (p.data.equals(x)) {
index = i;
}
i++;
p = p.next;
}
return index;
}
/**
* add
*
* @param x
*/
public void add(T x) {
Comparable<? super T> tmp = (Comparable<? super T>) x;
if (size == 0) {//空表情况,及插入位置0
head = new Node<>(x, head);
} else {//非空表情况
Node<T> p = head;
Node<T> temp = head;
int i;
for (i = 0; i < size; i++) {
if (tmp.compareTo((T) p.data) < 0)
break;
p = p.next;
}
if (i==0){//第一个位置的情况
head=new Node<>(x,head);
}else {//普通情况
p=head;
for (int j = 0; j < i-1; j++) {
p=p.next;
}
p.next=new Node<>(x, p.next);
}
}
++size;//调整size
}
/**
* clear
*/
public void clear() {
while (head != null) {// 从第1个结点开始,逐个删除
Node<T> q = head;// q待删除结点
head = head.next;// 下一个结点
q.data = null;// 帮助GC
q.next = null;
}
size = 0;
}
public String toString() {
StringBuilder str = new StringBuilder();
for (T elem : this)// 利用了实现了的迭代器
str.append(elem + " ");
return str.toString();
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj instanceof CLinkedList<?>) {
CLinkedList<?> rhd = (CLinkedList<?>) obj;
if (this.size != rhd.size)
return false;
for (Node<?> p = head, q = rhd.head; p != null; p = p.next, q = q.next) {
if (!p.data.equals(q.data))
return false;
}
return true;
}
return false;
}
public int hashCode() {
int result = 1;
for (Node<T> p = head; p != null; p = p.next)
result = result * 31 + p.data.hashCode();
return result;
}
@SuppressWarnings("unchecked")
private CLinkedList<T> superClone() {
try {
return (CLinkedList<T>) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}
public Object clone() {
CLinkedList<T> v = superClone();// v的head和size与this的head和size相同
if (v.head == null)// 空链表
return v;
// 为v分配新的结点,不能与this共用
v.head = new Node<>(head.data, null);
for (Node<T> p = head.next, q = v.head; p != null; p = p.next, q = q.next)
q.next = new Node<>(p.data, null);
return v;
}
public Iterator<T> iterator() {
return new Itr();
}
private class Itr implements Iterator<T> {// 注意Itr是内部类,而 Node是静态的嵌套类
private Node<T> currentNode;
public Itr() {
currentNode = head;
}
public boolean hasNext() {
return currentNode != null;
}
public T next() {
T data = currentNode.data;
currentNode = currentNode.next;
return data;
}
}
}
reverse逆序:
/**
* reverse
*/
public void reverse() {//逆序
if (head == null || head.next == null) return;
Node<T> p = head.next;//先指到第2个节点
head.next = null;//把第一个节点断开
while (p != null) {
Node<T> q = p.next;//后移
//将p插入头结点之后
p.next = head;
head = p;
p = q;//继续访问下一个元素
}
}
removerange删除区间:
/**
* removeRange
*
* @param from
* @param to
*/
public void removeRange(int from, int to) {
rangeCheck(from);
rangeCheck(to);//检查index
Node<T> from_h = head;
Node<T> to_b = head;
Node<T> p = head;//帮助GC的指针
if (from == 0) {//from在开头的情况
for (int i = 0; i < to + 1; i++) {
p = to_b.next;
to_b = null;
to_b = p;
}
head = to_b;
} else {//一般情况
for (int i = 0; i < to + 1; i++) {
if (i < from - 1) {
from_h = from_h.next;
}
p = to_b.next;
to_b = null;
to_b = p;
}
from_h.next = to_b;
}
size = size - (to - from + 1);//更改size
}
1. 检查from,to
2. 注意帮助GC,清空内存
3. 找到from的前驱节点指向to的后继节点即可
4. 删除注意更改size
lastindex该元素最后出现的位置:
/**
* lastIndex
*
* @param x
* @return
*/
public int lastIndex(T x) {
Node<T> p = head;
int index = -1;
int i = 0;
while (p != null) {
if (p.data.equals(x)) {
index = i;
}
i++;
p = p.next;
}
return index;
}
额.........找到返回即可
add直接添加,保证顺序正确
/**
* add
*
* @param x
*/
public void add(T x) {
Comparable<? super T> tmp = (Comparable<? super T>) x;
if (size == 0) {//空表情况,及插入位置0
head = new Node<>(x, head);
} else {//非空表情况
Node<T> p = head;
Node<T> temp = head;
int i;
for (i = 0; i < size; i++) {
if (tmp.compareTo((T) p.data) < 0)
break;
p = p.next;
}
if (i==0){//第一个位置的情况
head=new Node<>(x,head);
}else {//普通情况
p=head;
for (int j = 0; j < i-1; j++) {
p=p.next;
}
p.next=new Node<>(x, p.next);
}
}
++size;//调整size
}
1. 空表直接加入
2. compare找到位置
3. 找到前驱节点,使前驱节点指向该新建节点,该新建节点指向原前驱节点的next
4. 注意插入的位置