前言

  数据结构是为实现堆计算机数据有效使用的各种数据组织形式,服务于各类计算机操作。不同的数据结构具有各自对应的适用场景,目的是降低各种算法计算的时间与空间复杂度,达到最佳的任务执行效率。

  常见的数据结构包括:线性数据结构、非线性数据结构。具体为:数组、链表、栈、队列、树、图、散列表、堆

  

iOS 可变数组线程安全 可变数组和链表_数组

 数组

  数组是将相同类型的元素存储于连续内存空间的数据结构,其长度不变。

  如下图所示,构建此数组需要在初始化时给定长度,并对数组每个元素赋值。

 

   可变数组:是经常使用的数据结构,其基于数据和扩容机制实现,相比普通数组更加灵活。常用操作有:访问元素、添加元素、删除元素。ArrayList就是一种可变数组。

链表

  链表以节点为单位,每个元素都是一个独立对象,在内存空间的存储是非连续的。链表的节点对象具有两个成员变量:【值】,【后继节点引用】

  

class ListNode {
  int val;
  ListNode next;
  ListNode(int x) { val = x }        
}

  

iOS 可变数组线程安全 可变数组和链表_数组_02

 

 

 栈

  栈是一种具有先入后出特点的抽象数据结构,可使用数组或链表实现。

Stack<Integer> stack = new Stack<>();
// 入栈
stack.push(1);
stack.push(2);

// 出栈 2
stack.pop();

  

iOS 可变数组线程安全 可变数组和链表_数组_03

 

 

 队列

  队列是一种先入先出的特点抽象数据结构,可使用链表表现。

Queue<Integer> queue = new LinkedList<>();
queue.offer(1); // 元素1入队
queue.offer(2); // 元素2入队
queue.poll(); // 出队 -> 1
queue.poll(); // 出队 -> 2

  

iOS 可变数组线程安全 可变数组和链表_iOS 可变数组线程安全_04

 

 

 树

  树是一种非线性数据结构,根据子节点数量可分为【二叉树】和【多叉树】,最顶层的节点称为【根节点 root】。以二叉树为例,每个节点包含三个成员变量:【val 值】、【左子节点 Left】、【右子节点 right】。

class TreeNode {
  int val;
  TreeNode left;
  TreeNode right;
  TreeNode(int x) { val = x;}  
}

  

iOS 可变数组线程安全 可变数组和链表_链表_05

 

 

 图

  图是一种非线性数据结构,由【节点(顶点)vertex】和【边 edge】组成,每条边连接一对顶点。根据边的方向有无,图可分为【有向图】和【无向图】。

  如下图所示,此无向图的 顶点边 集合分别为:

  • 顶点集合:vertices = {1,2,3,4,5}
  • 边集合:edges = {(1,2),(1,3),(1,4),(1,5),(2,4),(3,5),(4,5)}

iOS 可变数组线程安全 可变数组和链表_数组_06

 

 

 表示图的方法通常有两种:

  邻接矩阵   

    使用数组 verticesvertices 存储顶点,邻接矩阵 edgesedges 存储边; edges[i][j]edges[i][j] 代表节点 i + 1i+1 和 节点 j + 1j+1 之间是否有边。

    

iOS 可变数组线程安全 可变数组和链表_数据结构_07

 

 

 

  邻接表

    使用数组 verticesvertices 存储顶点,邻接表 edgesedges 存储边。 edgesedges 为一个二维容器,第一维 ii 代表顶点索引,第二维 edges[i]edges[i] 存储此顶点对应的边集和;例如 edges[0] = [1, 2, 3, 4]edges[0]=[1,2,3,4] 代表 vertices[0]vertices[0] 的边集合为 [1, 2, 3, 4][1,2,3,4] 。

  

iOS 可变数组线程安全 可变数组和链表_链表_08

 

 

 散列表

  散列表是一种非线性数据结构,通过利用Hash函数将指定的【键 key】映射至对应的【值 value】,以实现高效的查找。

// 初始化散列表
Map<String, Integer> dic = new HashMap<>();

// 添加 key -> value 键值对
dic.put("小力", 10001);
dic.put("小特", 10002);
dic.put("小扣", 10003);

// 从姓名查找学号
dic.get("小力"); // -> 10001
dic.get("小特"); // -> 10002
dic.get("小扣"); // -> 10003

iOS 可变数组线程安全 可变数组和链表_链表_09

 

 

 堆

   堆是一种基于【完全二叉树】的数据结构,可使用数组实现。以堆为原理的排序算法称为【堆排序】,结构为【优先队列】。堆分为【大顶堆】和【小顶堆】:任意节点的值不大于(小于)其父节点的值。

完全二叉树定义:设二叉树深度为k,若二叉树除第k层外的其它各层(第1至 k -1 层)的节点达到最大个数,且处于第k层的节点都连续集中在最左边,则称此二叉树为完全二叉树。

如下图所示:包含1、4、2、6、8元素的小顶堆。将堆(完全二叉树)中的节点按层编号,即可映射到右边数组存储形式。

iOS 可变数组线程安全 可变数组和链表_链表_10

 

 

 通过使用「优先队列」的「压入 push()」和「弹出 pop()」操作,即可完成堆排序,实现代码如下:

// 初始化小顶堆
Queue<Integer> heap = new PriorityQueue<>();

// 元素入堆
heap.add(1);
heap.add(4);
heap.add(2);
heap.add(6);
heap.add(8);

// 元素出堆
heap.poll(); // ->1
heap.poll(); // -> 2
heap.poll(); // -> 4
heap.poll(); // -> 6
heap.poll(); // -> 8