顺序表和链表
1. 线性表
定义:线性表是由n个具有相同特性的数据元素组成的有限序列,表中每个元素具有相同元素。逻辑上为连续的线性结构。
常见的线性表:顺序表,链表、栈、队列、字符串
线性表根据物理储存方式分为:顺序表和链表
线性表在逻辑上是线性结构,在物理上并不是连续的,线性表在物理上储存时,通常是以数组和链式结构的形式储存。
动态数组:底层仍然使用数组,但支持动态扩容 不属于动态数据结构。
动态数据结构:需要多少空间,就开辟多少空间。eg:链表 ; 类比 火车
逻辑上连续,物理上不一定连续
线性表分析:
1.1客户端
1.不能直接使用Node 节点,客户端只需关心数据的储存而不关心节点间的关系,因此将Node 作为内部类隐藏起来
LinkedList: 相当于火车 ,由多个节点组成具体来连接每个节点,客户端使用此类 ;
Node: 相当于火车节点,负责存放数据
1.2 数据如何储存
优化点: 由于在任意位置插入节点时需要判断是否是头节点的插入,因为头节点没有前驱节点。引入一个dummyHead,虚拟头节点。保证任意存放数据的节点都一定会有前驱节点。
节点:数据+下个节点地址
客户端:不能直接使用Node节点
1.3 顺序表
1.3.1顺序表特性
优点:便于随机访问
缺点:不便于插入、删除(末尾插入或删除比较方便)
场景:需要大量访问元素,尾删,尾插较多时使用顺序表。
1.3.2 顺序表的一些OJ
快慢指针找中间节点
package Ds.FindK;
/**
* @Name: 找倒数第K个节点
* @Author:ZYJ
* @Date:2019-04-29-16:07
* @Description: 利用快慢指针找倒数第K个节点
*/
public class FindK {
public static void main(String[] args) {
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(5);
ListNode node5 = new ListNode(6);//3
ListNode node6 = new ListNode(7);
ListNode node7 = new ListNode(8);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = node6;
node6.next = node7;
FindK findK = new FindK();
ListNode result = findK.FindKToTail(node1, 3);
System.out.println(result.val);
}
public static class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
public ListNode FindKToTail(ListNode head, int k) {
if (head != null) {
ListNode F = head;
ListNode S = head;
for (int i = 0; i < k; i++) {
if (F != null) {
F = F.next;
} else {
return null;
}
}
while (F != null) {
F = F.next;
S = S.next;
}
return S;
}
return null;
}
}
1.4 链式表
链表:将采用一组地址任意的储存单元存放线性表中的数据元素。在逻辑上连续,在物理上不连续。链式结构的线性表不会按线性的逻辑顺序来保持数据元素,它需要在每一个数据元素里储存下一个元素的地址。
1.4.1 单链表
单链表指的是每个节点只保留一个引用,该引用指向当前节点 的下一个节点,没有引用指向头节点,尾结点的next指向空。
单链表分析:
优点:1,删除与插入效率高
2,有元素才会分配结点,不会有闲置的结点
3,长度不固定,储存空间不需要连续
缺点:不支持随机查找,只能从前驱结点找到后继结点而无法从后继结点找到前驱结点
1.4.2 双向链表
每个结点保留两个引用 prev和next ,prev保存前驱结点,next保存后继结点。
双链表分析:
优点:删除指定所有下的节点性能更好
缺点:添加,删除节点时的指针维护成本较大
1.4.3 循环链表
循环链表是一种收尾相接的链表,将单链表的尾结点的后继指向头节点,就形成了循环链表
特点:从链表的任意一个节点出发都可以找到其他所有节点。
循环链表可以解决“约瑟夫环问题”