From 8c88d393870475466506d7ac1e459504101e719b Mon Sep 17 00:00:00 2001 From: ranwenjie Date: Sun, 7 Nov 2021 01:15:35 +0800 Subject: [PATCH] update readme --- 2 List/README.md | 10 +++++- 4 Tree/8-堆/堆.md | 42 ++++++++++++++++++++++ 4 Tree/README.md | 4 +++ 5 Graph/README.md | 9 ++++- 6 Sort/README.md | 33 +++--------------- 9 Algorithms Job Interview/README.md | 52 +++++++++++++++++++++++++--- README.md | 2 ++ 7 files changed, 118 insertions(+), 34 deletions(-) diff --git a/2 List/README.md b/2 List/README.md index 1e0460f..a8a29af 100644 --- a/2 List/README.md +++ b/2 List/README.md @@ -25,11 +25,19 @@ java 中扩容,每次扩容新增原先容量的 1/2 ### 链表 VS 数组 +特点 -* 查询: 数组 O(1), 内存连续, 有序时可以用二分查找;有界 +* 数组 : 内存连续, 更好利用局部性原理;内存空间必须一次性分配够,所以说数组如果要扩容,需要重新分配一块更大的空间,再把数据全部复制过去,有界 +* 链表 : 不存在数组的扩容问题, 空间不连续,你无法根据一个索引算出对应元素的地址,所以不能随机访问; 需要前后元素位置的指针,会消耗相对更多的储存空间 + +优缺点: + +* 查询: 数组 O(1), 有序时可以用二分查找; * 删除: 链表只需要移动指针 O(1) ,数组的话删除元素需要移动后续的元素 O(N) + + ## 双向链表 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。 diff --git a/4 Tree/8-堆/堆.md b/4 Tree/8-堆/堆.md index 16bb213..73f9773 100644 --- a/4 Tree/8-堆/堆.md +++ b/4 Tree/8-堆/堆.md @@ -1,5 +1,47 @@ # 大顶堆 和 小顶堆 +先来了解下 `堆` 结构; 堆也被称为`优先队列` ; + +特点 + +* 堆总是一颗完全二叉树树, 使用数组作为其存储结构; +* 任一节点小于(或大于)其所有的孩子节点; + + +堆分小根堆和大根堆; 如果是大于所有孩子节点,这就是一颗大根堆,也就是根节点是堆上的最大值;如果节点小于所有的子节点,这就是一颗小跟堆,也即是根节点是堆上所有节点的最小值。 + + + +### 应用场景 + +* 优先队列 如iOS中的NSOperationQueue 就是维护一个优先队列 +* 堆排序 +* top-K 大(小) + + + +# 堆存储结构 + + +`堆用数组来存储`,因为是一颗完全二叉树,i节点的父节点索引就是(i-1)/2, 左右子节点小标是 2i+1,2i+2。 + +堆的操作有: + +* 建堆 +* 插入:都是插入到数组最后,然后再调整满足堆次序 +* 删除:删除总是发生在 A[0]处,也就是只删除根节点 + +这样难怪`堆`被称为 `优先队列`。 插入和删除分别在 数组尾部和头部,只是需要再次调整以满足堆次序。 + + + + + + + + + + diff --git a/4 Tree/README.md b/4 Tree/README.md index 1b16e27..b163486 100644 --- a/4 Tree/README.md +++ b/4 Tree/README.md @@ -16,6 +16,10 @@ * 赫夫曼编码 Huffman +## 二叉树 + + + ## [二叉查找树](2-二叉查找树/二叉查找树.md) 快速排序就是个二叉树的前序遍历,归并排序就是个二叉树的后序遍历 diff --git a/5 Graph/README.md b/5 Graph/README.md index a4d7452..0774d79 100644 --- a/5 Graph/README.md +++ b/5 Graph/README.md @@ -37,10 +37,17 @@ # 图的存储结构 * 对象和指针 -* 矩阵 +* 邻接矩阵 (二维数组) * 邻接表 +图数据结构表示: + +``` + +``` + + ## 图的操作 #### 遍历 diff --git a/6 Sort/README.md b/6 Sort/README.md index 0e4508a..20636e4 100644 --- a/6 Sort/README.md +++ b/6 Sort/README.md @@ -246,40 +246,17 @@ public void merge(int[] arr,int low,int mid,int high,int[] tmp){ 利用堆这种数据结构设计的一种排序算法 -先来了解下 `堆` 结构 - -堆分小根堆和大根堆 - -堆: 任一节点小于(或大于)其所有的孩子节点,如果是大于所有孩子节点,这就是一颗大根堆,也就是根节点是堆上的最大值;如果节点小于所有的子节点,这就是一颗小跟堆,也即是根节点是堆上所有节点的最小值。 - -堆也被称为`优先队列` -堆总是一颗完全树 - -`堆用数组来存储`,i节点的父节点就是(i-1)/2,左右子节点小标是 2i+1,2i+2。 - -堆的操作有: - -建堆 -插入:都是插入到数组最后,然后再调整满足堆次序 -删除:删除总是发生在 A[0]处,也就是只删除根节点 - -这样难怪`堆`被称为 `优先队列`。插入和删除分别在 数组尾部和头部,只是需要再次调整以满足堆次序。 - -`堆`的应用场景有: -优先队列 如iOS中的NSOperationQueue 就是维护一个优先队列 -堆排序 - - +[堆结构参考这里](../4%20Tree/8-堆/堆.md) 我们来看看如何使用`堆` 来做排序? -1.将待排序数列看做一颗完全二叉树的存储结构 -2.`堆化数组`,结束后,根a[0]变成了最小的值(小根堆) -3.取a[0]值,然后对`堆`做删除操作,此时,`堆`会重新 `堆化数组`,a[0]又是下一个最小的值。 +1. 将待排序数列看做一颗完全二叉树的存储结构 +2. `堆化数组`,结束后,根a[0]变成了最小的值(小根堆) +3. 取a[0]值,然后对`堆`做删除操作,此时,`堆`会重新 `堆化数组`,a[0]又是下一个最小的值。 删除操作通常是先把数组最后的元素提到a[0]位置,然后从根节点开始进行一次从上向下的调整;调整时,先从左右孩子中找最小的交换。如果父节点比每个节点都小就不用调整。(因此,在`堆排序`是可以直接让 a[0]和数组最后一个元素互换,但要先保存好a[0],或者a[n-1],这样导致了使用`堆排序`时,递增排序使用大根堆,递减排序使用小根堆。) 4. 循环3,就可以按从小到大的顺序取出所有数组元素。 -堆排序主要时间花在建堆期间和`堆化数组`,找数列中最大树只需要O(1)时间复杂度 +堆排序主要时间花在建堆期间和`堆化数组`,找数列中最大数只需要O(1)时间复杂度 void heap_sort(int *a, int length){ diff --git a/9 Algorithms Job Interview/README.md b/9 Algorithms Job Interview/README.md index 08a9ad1..c39960f 100644 --- a/9 Algorithms Job Interview/README.md +++ b/9 Algorithms Job Interview/README.md @@ -79,20 +79,64 @@ +# 刷题框架套路 + +遍历 + +``` +# 数组遍历框架 +void traverse(int[] arr) { + for (int i = 0; i < arr.length; i++) { + // 迭代访问 arr[i] + } +} + +# 链表遍历框架 +void traverse(ListNode head) { + for (ListNode p = head; p != null; p = p.next) { + // 迭代访问 p.val + } +} + +``` -## [《剑指offer》](剑指offer/README.md) +递归 -《剑指offer》里面给出了50到高质量的算法问题,很有学习的必要。 +``` +# 链表递归 +void traverse(ListNode head) { + // 递归访问 head.val + traverse(head.next); +} -## [《编程之美》](编程之美/README.md) +# 二叉树递归 +void traverse(TreeNode root) { + traverse(root.left); + traverse(root.right); +} + +# 多叉树递归 +void traverse(TreeNode root) { + for (TreeNode child : root.children) + traverse(child); +} + +# 图的递归:,用个布尔数组 visited 做标记就行了 +``` + + + +# 参考 [九度OJ](http://ac.jobdu.com/index.php) [leetcode 题目](https://leetcode.com/) - +[labuladong 的算法小抄](https://labuladong.gitee.io/algo/1/2/) +[《剑指offer》](剑指offer/README.md) 《剑指offer》里面给出了50到高质量的算法问题,很有学习的必要。 +[《编程之美》](编程之美/README.md) diff --git a/README.md b/README.md index 125f83f..ebc3c05 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,8 @@ * 链表 * 双向链表 +数组和链表结构是基础结构,散列表、栈、队列、堆、树、图等等各种数据结构都基于数组和链表结构实现。 + ### [队列](2%20Queue/README.md) * 队列