LinkedList
Node结点
- data域
- 下个结点的指向
Node结点代码
private class Node {
public E e;
public Node next;
public Node(E e, Node next) {
this.e = e;
this.next = next;
}
public Node(E e) {
this(e, null);
}
public Node() {
this(null, null);
}
@Override
public String toString() {
return e.toString();
}
}
链表结构表达
- 链表中需要头结点
- Node head = new Node();
- 需要size记录拥有的元素个数
public class LinkedList<E> {
private Node head;
private int size;
/***构造函数***/
//只需要空参构造函数
public LinkedList(){
head = null;
size = 0;
}
/*******增*******/
// 这因为,头结点和中间结点有差异,所以需要分别讨论。此处可以优化
public void add(int index, E e){
//判断index是否正确
if(index < 0 || index>size){
throw new IllegalArgumentException("Add failed.Illegal index");
}
//判断当index为0的时候进行头部添加
if(index == 0){
addFirst(e);
}else{
//当不为头结点时,建立结点指针prev从头结点开始遍历到指定index位置
Node prev = head;
for(int i = 0;i<index-1;i++){
prev = prev.next;
}
//在此处插入节点
prev.next = new Node(e,prev.next);
//size++
size++;
}
}
public void addFirst(E e){
// Node node = new Node(e);
// node.next = head;
// head = node;
// 简化书写
head = new Node(e,head);
size++;
}
public void addLast(E e){
add(size, e);
}
/*********查*******/
//获取链表中的元素个数
public int getSize(){
return size;
}
//返回链表是否为空
public boolean isEmpty(){
return size==0;
}
/******改******/
public void set(int index,E e){
if(index < 0 || index>size){
throw new IllegalArgumentException("Set failed.Illegal index");
}
//从头结点,开始遍历
Node prev = head;
for(int i = 0;i<index;i++){
prev = prev.next;
}
prev.e = e;
}
/*****************删******************/
public E remove(int index){
if (index < 0 || index>=size){
throw new IllegalArgumentException("Removed failed.Illegal index");
}
//建立结点引用prev,遍历到要删除节点的头一个节点
Node prev = head;
for(int i = 0;i<index;i++){
prev = prev.next;
}
//建立删除结点引用delNode,prev.next
Node delNode = prev.next
//prev的下一个结点跳过删除结点,指向下下个结点
prev.next = prev.next.next;
//将要删除的结点指向下一个结点的引用赋值为null
delNode.next = null;
size -- ;
//返回删除结点的数据域
return delNode.e;
}
public E removeFirst(){
remove(0);
}
public E removeLast(){
remove(size - 1);
}
}
注意:是结点是引用,指向同一个地址的结点,不论是哪一个结点修改,其余结点也会被动修改。
head 结点只是存储,链表的起始位置信息,不存储其他信息。
这样要分两次考虑,
- 第一个结点【区分head】
- 中间结点
为了简化思考方式,可以优化,在第一个结点(不是head)之前加一个不存任何数据的结点dummyNode,这样所有要操作的结点都是中间结点。不用思考第一个结点