链表专题:
1.简单手写创建一个单链表
//创建了一个单链表
//数组是固定长度的一个数据结构,链表是可任意拓展的数据结构
public 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;
}
}
2.单链表的增删改查
public class MyLinkedList(){
int size; //链表大小
ListNode head;//虚拟头结点
//无参构造 初始化链表
public MyLinkedList(){
size = 0;
head = new ListNode(0);
}
//获取第index个节点的数值
public int get(int index){
//题干要求 如果索引无效,则返回-1
if (index >= size || index < 0) {
return -1;
}
//索引有效
ListNode currentNode = head; //从头结点开始查
//为什么i<= index? 链表查询是从头遍历。查到index的时候就已经得到结果了,不需要往下查
//所以链表查询非常耗时
for (int i=0;i<=index;i++) {
currentNode = currentNode.next;
}
return currentNode.val;
}
//在链表最前面插入一个节点
public void addAtHead(int val) {
addAtIndex(0, val);
}
//在链表的最后插入一个节点
public void addAtTail(int val) {
addAtIndex(size, val);
}
// 插入元素分三种特殊情况
// 在第 index 个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。
// 如果 index 等于链表的长度,则说明是新插入的节点为链表的尾结点
// 如果 index 大于链表的长度,则返回空
public void addAtIndex(int index, int val){
//如果 index 大于链表的长度,则返回空
if (index > size) {
return;
}
//题干要求
if (index < 0) {
index = 0;
}
size++; //先扩容
//找到要插入节点的前驱
ListNode pred = head;
for (int i = 0; i < index; i++) {
pred = pred.next;
}
//增加一个结点
ListNode toAdd = new ListNode(val);
//更改指针的指向
toAdd.next = pred.next;
pred.next = toAdd;
}
//删除第index个节点
public void deleteAtIndex(int index){
if (index >= size || index < 0) {
return;
}
size--; //先减
//找到要插入节点的前驱
ListNode pred = head;
for (int i = 0; i < index; i++) {
pred = pred.next;
}
//还要找到节点的后驱
pred.next = pred.next.next;
}
}
3.链表反转(经典链表算法题 大厂高频) 难度 easy
力扣https://leetcode-cn.com/problems/reverse-linked-list/
public ListNode reverseList(ListNode head) {
//题干提供的数据为单链表 [1->2->3->4->5] head是val=1的结点
//双指针法
ListNode prev = null;//定义一个前结点
ListNode cur = head;//把cur当做头结点
ListNode temp = null;//定义一个临时结点做交换用 和冒泡排序中的temp功能类似
while (cur != null) {//注释为第一次循环过程
temp = cur.next;//cur = head = 1,先用temp保存cur的下一个结点 也就是元素值为2的结点
cur.next = prev;//如果之前没学过指针的话 这一步比较难理解 =的意思是指向 不是赋值 cur的下一个结点是prev
prev = cur;//开始反转 prev此时为1
cur = temp;//cur为2 循环结束
}
return prev;
}
public ListNode reverseList(ListNode head) {
//题干提供的数据为单链表 [1->2->3->4->5] head是val=1的结点
//递归法
return reverse(null, head);
}
private ListNode reverse(ListNode prev,ListNode cur){
if(cur == null) return prev;
ListNode temp = cur.next;
cur.next = prev;
return reverse(cur,temp);
}