学习数据结构的框架思维
作者:互联网
学习数据结构的框架思维
1. 数据结构千变万化,但万变不离宗
最高层的抽象,数据结构只有两种:数组和链表。
数组和链表才是「结构基础」,散列表、栈、队列等都可以看成是上层建筑,
依次来讲解‘上层建筑’怎么通过结构基础来实现
- 比如说「队列」、「栈」这两种数据结构既可以使用链表也可以使用数组实现。用数组实现,就要处理扩容缩容的问题;用链表实现,没有这个问题,但需要更多的空间存储节点指针
- 「图」的两种表示方法,邻接表就是链表,邻接矩阵就是二维数组。邻接矩阵判断连通性迅速,并可以进行矩阵运算解决一些问题,但是一般比较耗费空间。邻接表比较节省空间,但是时间上肯定不如邻接矩阵快。
- 「散列表」就是通过散列函数把键映射到一个大数组里。而且对于解决散列冲突的方法,拉链法需要链表特性,操作简单,但需要空间;线性探查法就需要数组特性,以便连续寻址,省空间,但操作稍微复杂些。
- 「树」,用数组实现就是「堆」,因为「堆」是一个完全二叉树,用数组存储不需要节点指针,操作也比较简单;用链表实现就是很常见的那种「树」,因为不一定是完全二叉树,所以不适合用数组存储。为此,在这种链表「树」结构之上,又衍生出各种巧妙的设计,比如二叉搜索树、AVL 树、红黑树、区间树、B 树等等,以应对不同的问题。
总结:没有完美的数据结构
2、数据结构的操作:遍历 + 访问,具体一点:增删改查
遍历 + 访问:线性/非线性的
线性:for / while 为代表,非线性:递归为代表
数组遍历框架
void traverse(int[] arr) {
for (int i = 0; i < arr.length; i++) {
// 访问 arr[i]
}
}```
**二叉树遍历框架,典型的非线性递归遍历结构:**
```java
void traverse(TreeNode root) {
traverse(root.left)
traverse(root.right)
}
上面只是最简单的形式,可以随意改造
链表遍历框架,兼具线性和非线性遍历结构:
void traverse(ListNode head) {
for (ListNode p = head; p != null; p = p.next) {
// 访问 p.val
}
}
void traverse(ListNode head) {
// 访问 head.val
traverse(head.next)
}
二叉树框架又可以扩展为N叉树遍历框架:
void traverse(TreeNode root) {
for (TreeNode child : root.children)
traverse(child)
}
N 叉树的遍历又可以扩展为图的遍历,因为,图就是好几 N 叉棵树的结合体。你说图是可能出现环的?这个很好办,用个布尔数组 visited 做标记就行了
所谓框架,就是说不管具体问题是什么,这些代码都是永远无法脱离的结构,你可以把这个结构作为大纲,根据具体问题在框架上添加代码就行了。
3、为什么算法总是和数据结构同时出现
数据结构是工具,算法是通过合适的工具解决问题的方法。
初学算法的时候,一定要从第二点上面从框架上看问题,而不是纠结于细节问题,
标签:思维,traverse,遍历,框架,链表,数组,数据结构 来源: https://blog.csdn.net/A13526_/article/details/120917637