1.基本结构
链表是一种链式存储的线性表,所有元素的内存地址不一定是连续的
2.前期准备
一个Node里面包含一个元素(element)和一个结点(node<E>):
private Node<E> first; // 创建头节点
private E element; // 元素
pirvate Node<E> next; // 下一个节点
//构造函数(创造Node)
public Node(E element, Node<E> next) {
this.element = element;
this.next = next;
}
// 边界条件
public void rangeCheck(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("索引越界");
}
}
public void rangeCheckForAdd(int index) {
if (index < 0 || index > size) {
outOfBounds(index);
}
}
// 根据index获取对应的node<E>
private Node<E> node(int index) {
rangeCheck(index);
Node<E> node = first; //创建头结点
for (int i = 0; i < index; i++) {
node = node.next;
}
return node;
}
3.代码实现
// 清除操作
public void clear() {
size = 0; //size清零
first = null; //头尾结点指向空
}
// 根据index获取元素
// 最好:O(1) 最坏:O(n) 平均:O(n)
public E get(int index){
return node(index).elment;
}
// 添加操作
// 最好:O(1) 最坏:O(n) 平均:O(n)
public void add(int index,int element){
rangeCheckforAdd(index);
if(index==0){ // 如果插入的是头节点的话
first = new Node<>(element,first);
}
else{
Node<E> prev = node(index-1); //发现尾节点符合要求,而头节点不符合
prev.next= new Node<>(element,prev.next);
}
size++;
}
// 删除操作
// 最好:O(1) 最坏:O(n) 平均:O(n)
public void remove(int index){
rangeCheck(index)
Node<E> node = first; //创造头节点
if(index==0){
first = first.next;
}
else{
Node<E> prev = node(index-1);
pre.next = prev.next.next;
}
size--;
}
// 根据element找node
public int indexOf(E element){
if(element==null){ //因为null中没有equals方法
Node<E> node = first;
for (int i = 0; i < size; i++) {
if(node.element==null){
return i;
}
node=node.next;
}
}
else{
Node<E> node = first; //创建头节点
for (int i = 0; i < size; i++) {
if(element.equals(node.element)){
return i;
}
node=node.next;
}
}
return -1;
}
4.练习题
4.1 删除结点
// 删除结点
public void deleteNode(ListNode node){
node.val= node.next.val;
node.next=node.next.next;
}
4.2 反转链表
// 递归方法
public ListNode reverseList(ListNode head){
// 如果没有结点或者只有一个结点,直接返回
if(head==null || head.next=null) return head;
List newHead = reverseList(head.next);
head.next.next=head;
head.next=null;
return newHead;
}
// 迭代方法
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) return head;
ListNode newHead = null; //创造一个newHead
while (head != null) {
ListNode temp = head.next; //防止被回收
// 开始反转
head.next = newHead;
newHead = head;
head = temp; //为下一次迭代做准备
}
}
4.3 判断链表是否有环
public boolean hasCycle(ListNode head){
if(head==null||head.next==null) return false;
ListNode slow = head; // 创建慢指针
ListNode fast = head.next; //创建快指针
while( fast!=null&&fast.next!=null ){
if(slow==fast) return true;
slow = slow.next;
fast = fast.next.next;
}
return false;
}