在讨论链表(linked-list)之前,需要明确几个概念:线性表(顺序表, list, linear list), 数组(array),链表(linked-list)。
线性表:线性表也叫作顺序表,它是最基础、最简单、最常用的一种基本数据结构,线性表总存储的每个数据称为一个元素,各个元素及其索引是一一对应的关系。线性表有两种存储方式:顺序存储方式和链式存储方式。
数组(array):数组就是线性表的顺序存储方式。数组的内存是连续分配的,并且是静态分配的,即在使用数组之前需要分配固定大小的空间。可以通过索引直接得到数组中的而元素,即获取数组中元素的时间复杂度为O(1)。
链表(linked-list):链表就是线性表的链式存储方式。链表的内存是不连续的,前一个元素存储地址的下一个地址中存储的不一定是下一个元素。链表通过一个指向下一个元素地址的引用将链表中的元素串起来。
1.单向链表:
单向链表节点结构:
data域:存储数据元素信息的域称为数据域
next域:存储直接后继位置的域称为指针,它是存放节点的直接后继的地址(位置)的指针域
data域+next域:组成数据ai的存储映射,称为节点
注意:链表通过每个节点的指针域将线性表的n个节点按其逻辑顺序连接在一起的
public class Node {
public int value;
public Node next;
public Node(int data) {
value = data;
}
}
2.双向链表
双向链表节点结构
顾名思义,双向链表就是有两个方向的链表。同单向链表不同,在双向链表中每一个节点不仅存储指向下一个节点的指针,而且存储指向前一个节点的指针。通过这种方式,能够通过在O(1)时间内通过目的节点直接找到前驱节点,但是同时会增加大量的指针存储空间。
public class DoubleNode {
public int value;
public DoubleNode last;
public DoubleNode next;
public DoubleNode(int data) {
value = data;
}
}
3.单链表与双链表的简单coding练习
1)单链表和双链表如何反转
遍历法:遍历法就是在链表遍历的过程中将指针顺序置换
// head
// a -> b -> c -> null
// c -> b -> a -> null
public static Node reverseListedList(Node head) {
Node pre = null;
Node next = null;
while(head != null) {
next = head.next;
head.next = pre;
pre = head;
head = next;
}
return pre;
}
代码解析:例如:1->2->3->4
- 准备两个空结点 pre用来保存先前结点、next用来做临时变量
- 在头结点head遍历的时候此时为1结点
- next = 1结点.next (2结点)
- 1结点.next=pre(null)
- pre = 1结点
- head = 2结点
- 进行下一次循环head=2结点
- next = 2结点.next (3结点)
- 2结点.next=pre(1结点)=>即完成2->1
- pre = 2结点
- head = 3结点
- 进行循环...
双链表的反转:
public static DoubleNode reverseDoubleList(DoubleNode head) {
DoubleNode pre = null;
DoubleNode next = null;
while(head != null) {
next = head.next;
head.next = pre;
head.last = next;
pre = head;
head = next;
}
return pre;
}
2)把给定值都删除
public class Code02_DeleteGivenValue {
public static class Node{
public int value;
public Node next;
public Node(int data) {
this.value = data;
}
}
//head = removeNode(head,2)
public static Node removeNode(Node head,int num) {
//head来到第一个不需要删除的位置
while(head != null) {
if(head.value != num) {
break;
}
head = head.next;
}
Node pre = head;
Node cur = head;
while(cur != null) {
if(cur.value == num) {
pre.next= cur.next;
}else {
pre = cur;
}
cur = cur.next;
}
return head;
}
}
4.栈和队列
逻辑概念 栈:数据先进后出,犹如弹匣
队列:数据先进先出,好似排队