学习内容来源于:https://labuladong.gitbook.io/algo/
以下是自己的归纳与总结。
示例代码均采用 Java。
数据结构的存储方式
数据结构的存储方式只有两种:**数组(顺序存储)和链表**(链式存储)。
散列表、栈、队列、堆、树、图等常见的数据结构,本质上都是数组与链表的实现形式,API不同而已。
数组
优点:连续空间存储,可以随机访问,通过索引快速定位到具体元素。
缺点:
- 扩容时需要重新分配一整块空间,再把元素全部复制过去,时间复杂度 O(N);
- 在特定位置插入或删除元素时,需要移动特定位置后面的全部元素,时间复杂度 O(N);
链表
优点:不存在扩容的问题,只需知道特定位置的前驱和后驱操作指针即可,时间复杂度 O(1)。
缺点:
- 空间不连续,不支持随机访问。
- 每个元素需记录前后指针,消耗一定的空间。
数据结构的基本操作
增删改查 其实就是遍历+访问。
散列表、栈、队列、堆、树、图等数据结构的出现,就是要高效的遍历和访问数据。
遍历和访问本质上只有两种,线性和非线性
线性: for/while 迭代为代表
非线性:递归
数组遍历
void traverse(int[] arr) {for (int i = 0; i < arr.length; i++) {// 迭代访问 arr[i]}}
链表遍历
/* 基本的单链表节点 */class ListNode {int val;ListNode next;}void traverse(ListNode head) {for (ListNode p = head; p != null; p = p.next) {// 迭代访问 p.val}}void traverse(ListNode head) {// 递归访问 head.valtraverse(head.next);}
递归
二叉树
/* 基本的二叉树节点 */class TreeNode {int val;TreeNode left, right;}void traverse(TreeNode root) {traverse(root.left);traverse(root.right);}
二叉树遍历与链表遍历相似,节点的数据结构也相似。
同理n叉树可得出:
n叉树
/* 基本的 N 叉树节点 */class TreeNode {int val;TreeNode[] children;}void traverse(TreeNode root) {for (TreeNode child : root.children)traverse(child);}
总结
数据结构的存储方式就是链表和数组,遍历就是迭代和递归。
