链表
链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。
链接的入口节点称为链表的头结点也就是head。
单链表
链表中的指针域只能指向下一个节点
单链表实现
class ListNode{
int val;
ListNode next;
public ListNode(){
}
public ListNode(int val){
this.val = val;
}
public ListNode(int val,ListNode next){
this.val = val;
this.next = next;
}
}
单链表的基本操作
在指定位置添加节点
步骤:
1.在链表的头节点添加一个虚拟头节点指向链表的头节点
2.将要添加的节点指针域指向指定位置的下一个节点
3.将要添加的节点指针域指向指定位置的上一个节点的指针域指向该节点
注意:
步骤2,3不可颠倒否则将造成链表丢失
删除指定位置的节点
步骤:
1.在链表的头节点添加一个虚拟头节点指向链表的头节点
2.将要删除的节点的上一个节点的指针域指向该节点的下一个节点
得到指定位置上的节点
步骤:
遍历节点返回指定位置上的节点
题目练习
题目一:力扣练习题:设计链表
代码实现:
class MyLinkedList {
int size;
ListNode head;
//设置虚拟头节点
public MyLinkedList() {
size = 0;
head = new ListNode(0);
}
//获取指定位置上的节点元素
public int get(int index) {
if(index >= size || index < 0) {
return -1;
}
ListNode temp = head;
//i <= index是因为此时temp指向的是虚拟头节点,所以要向后多遍历一位
for(int i = 0; i <= index; i++){
temp = temp.next;
}
return temp.val;
}
//在链表头插入节点
public void addAtHead(int val) {
addAtIndex(0,val);
}
//在链表尾插入节点
public void addAtTail(int val) {
addAtIndex(size,val);
}
//在指定位置插入节点
public void addAtIndex(int index, int val) {
if(index > size){
return;
}
//判断插入的位置是否为链表的头
index = Math.max(0,index);
size++;
ListNode temp = head;
for(int i = 0; i < index; i++) {
temp = temp.next;
}
ListNode addNode = new ListNode(val);
addNode.next = temp.next;
temp.next = addNode;
}
//删除指定位置上的节点
public void deleteAtIndex(int index) {
if(index < size && index >= 0) {
size--;
ListNode temp = head;
for(int i = 0; i < index; i++) {
temp = temp.next;
}
temp.next = temp.next.next;
}
}
}
//构造单向链表类
class ListNode{
int val;
ListNode next;
public ListNode(int val){
this.val = val;
}
}
题目二:
思路:
反转链表既将链表的指向全部反向,例如 1 --> 2 --> 3 -->4 --> null 变为 null <-- 1 <-- 2 <-- 3 <-- 4
现在我们需要定义一个pre指针初始化为null,一个cur指针指向头节点,将cur指针指向pre,既完成
了第一次指向的改变,再将pre和cur指针向后移动一个节点继续此操作,直到cur指针指向为null。
在这里插入图片描述
代码实现:
public ListNode reverseList(ListNode head) {
if(head == null){
return head;
}
ListNode cur = head;
ListNode pre = null;
while(cur != null){
//存储当前节点的下一个节点
//如果确实此步会造成链表丢失
ListNode next = cur.next;
//改变链表的指向
cur.next = pre;
//将指向整体往后移一位
pre = cur;
cur = next;
}
return pre;
}