链表基础知识
1)链表
链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个结点的指针域指向null。
2)单链表
3)双链表
由两个指针域,一个数据域组成一个结点,一个指向上一个元素一个指向下一项元素。
4)循环链表
5)链表的存储方式
链表中的节点是散乱分布在内存的某地址上。各个节点通过指针串联在一起。
6)链表的操作(增删改插)
删除节点
在java中不需要回收删除节点的内存。
添加节点
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;
}
}
203.移除链表元素
题目链接:. - 力扣(LeetCode)
题目讲解:代码随想录
错误:1)访问结构体的成员:指针才能用->,正常元素用.
2)空值是小写null!
(1)直接使用原来的列表来进行删除操作
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeElements(ListNode head, int val) {
//删除值相同的头结点后,可能新的头结点也值相等,用循环解决
while(head!=null&&head.val==val){
head=head.next;
}
if(head==null)
return head;
ListNode prev=head;
//确保当前结点后还有结点
while(prev.next!=null){
if(prev.next.val==val){
prev.next=prev.next.next;
}else{
prev=prev.next;
}
}
return head;
}
}
(2) 设置一个虚拟头节点再进行移除结点的操作
class Solution {
public ListNode removeElements(ListNode head, int val) {
//创建一个虚拟头结点
ListNode dummyNode=new ListNode(val-1);
dummyNode.next=head;
ListNode prev=dummyNode;
//确保当前结点后还有结点
while(prev.next!=null){
if(prev.next.val==val){
prev.next=prev.next.next;
}else{
prev=prev.next;
}
}
return dummyNode.next;
}
}
(3)递归(烧脑)
class Solution {
public ListNode removeElements(ListNode head, int val) {
if(head==null)
return null;
head.next=removeElements(head.next,val);
if(head.val==val){
return head.next;
}else{
return head;
}
}
}
707.设计链表
题目链接:. - 力扣(LeetCode)
题目讲解:代码随想录
1)第一次提交
class MyLinkedList {
//元素个数
int size;
//链表虚拟头结点
ListNode head;
//初始化链表
public MyLinkedList() {
size = 0;
head = new ListNode(0);
}
//获得特定下标的节点的val
public int get(int index) {
//先判断坐标是否合法
if(index >= size || index < 0){
return -1;
}
//遍历寻找特定下标的节点
ListNode prev = head;
for(int i = 0;i <= index;i++){
prev = prev.next;
}
return prev.val;
}
//在链表的第一个元素位插入元素
public void addAtHead(int val) {
//生成节点
ListNode add = new ListNode(val);
//连接
add.next = head.next;
head.next = add;
//链表长度增加
size++;
}
//在链表的末尾插入元素
public void addAtTail(int val) {
ListNode pre = head;
while(pre.next != null){
pre = pre.next;
}
//生成新节点
ListNode add = new ListNode(val);
//连接
add.next = null;
pre.next = add;
//链表长度增加
size++;
}
//在特定下标节点之前插入新元素
public void addAtIndex(int index, int val) {
//判断下标是否合法
if(index > size){
return;
}else if(index < 0){
index = 0;
}
//链表长度
size++;
//找到插入位置
ListNode pre = head;
for(int i = 0;i < index;i++){
pre = pre.next;
}
//生成新节点
ListNode add = new ListNode(val);
//连接
add.next = pre.next;
pre.next = add;
}
//删除链表为Index的节点
public void deleteAtIndex(int index) {
//判断下标有效
if(index < 0 || index >= size){
return;
}
//链表长度
size--;
//找到删除位置
ListNode pre = head;
for(int i = 0;i < index;i++){
pre = pre.next;
}
pre.next = pre.next.next;
}
}
/**
* Your MyLinkedList object will be instantiated and called as such:
* MyLinkedList obj = new MyLinkedList();
* int param_1 = obj.get(index);
* obj.addAtHead(val);
* obj.addAtTail(val);
* obj.addAtIndex(index,val);
* obj.deleteAtIndex(index);
*/
2)第二次提交
class MyLinkedList {
//链表中元素个数 = 最大Index + 1
int size;
//虚拟头节点
ListNode head;
//初始化函数
public MyLinkedList() {
size = 0;
head = new ListNode(0);
}
//获取下标为index的节点的值
public int get(int index) {
//判断下标是否有效
if(index < 0 || index >= size){
return -1;
}
//遍历链表,寻找index节点
ListNode pre = head;
//i就是每次指向的节点下标
for(int i = 0;i <= index;i++){
pre = pre.next;
}
return pre.val;
}
//在头部插入一个结点
public void addAtHead(int val) {
//生成新节点
ListNode add = new ListNode(val);
//连接
add.next = head.next;
head.next = add;
//链表元素增加
size++;
}
//在尾部插入一个结点
public void addAtTail(int val) {
//生成新节点
ListNode add = new ListNode(val);
//寻找插入元素
ListNode pre = head;
while(pre.next != null){
pre = pre.next;
}
//连接
pre.next = add;
//链表元素增加
size++;
}
public void addAtIndex(int index, int val) {
//判断下标是否合法
if(index > size){
return;
}
if(index < 0){
index = 0;
}
//链表元素长度增加
size++;
//寻找插入元素的前一个元素
ListNode pre = head;
for(int i = 0;i < index;i++){
pre = pre.next;
}
//生成新节点
ListNode add = new ListNode(val);
//连接
add.next = pre.next;
pre.next = add;
}
public void deleteAtIndex(int index) {
//判断下标是否有效
if(index < 0 || index >= size){
return;
}
//链表长度-1
size--;
//找到删除的节点前一个节点所在位置
ListNode ex = head;
for(int i = 0; i < index;i++){
ex = ex.next;
}
ex.next = ex.next.next;
}
}
class ListNode {
int val;
ListNode next;
public ListNode(int val) {
this.val = val;
}
}
/**
* Your MyLinkedList object will be instantiated and called as such:
* MyLinkedList obj = new MyLinkedList();
* int param_1 = obj.get(index);
* obj.addAtHead(val);
* obj.addAtTail(val);
* obj.addAtIndex(index,val);
* obj.deleteAtIndex(index);
*/