update readme
This commit is contained in:
+9
-1
@@ -25,11 +25,19 @@ java 中扩容,每次扩容新增原先容量的 1/2
|
||||
|
||||
### 链表 VS 数组
|
||||
|
||||
特点
|
||||
|
||||
* 查询: 数组 O(1), 内存连续, 有序时可以用二分查找;有界
|
||||
* 数组 : 内存连续, 更好利用局部性原理;内存空间必须一次性分配够,所以说数组如果要扩容,需要重新分配一块更大的空间,再把数据全部复制过去,有界
|
||||
* 链表 : 不存在数组的扩容问题, 空间不连续,你无法根据一个索引算出对应元素的地址,所以不能随机访问; 需要前后元素位置的指针,会消耗相对更多的储存空间
|
||||
|
||||
优缺点:
|
||||
|
||||
* 查询: 数组 O(1), 有序时可以用二分查找;
|
||||
* 删除: 链表只需要移动指针 O(1) ,数组的话删除元素需要移动后续的元素 O(N)
|
||||
|
||||
|
||||
|
||||
|
||||
## 双向链表
|
||||
|
||||
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
|
||||
|
||||
@@ -1,5 +1,47 @@
|
||||
# 大顶堆 和 小顶堆
|
||||
|
||||
|
||||
先来了解下 `堆` 结构; 堆也被称为`优先队列` ;
|
||||
|
||||
特点
|
||||
|
||||
* 堆总是一颗完全二叉树树, 使用数组作为其存储结构;
|
||||
* 任一节点小于(或大于)其所有的孩子节点;
|
||||
|
||||
|
||||
堆分小根堆和大根堆; 如果是大于所有孩子节点,这就是一颗大根堆,也就是根节点是堆上的最大值;如果节点小于所有的子节点,这就是一颗小跟堆,也即是根节点是堆上所有节点的最小值。
|
||||
|
||||
|
||||
|
||||
### 应用场景
|
||||
|
||||
* 优先队列 如iOS中的NSOperationQueue 就是维护一个优先队列
|
||||
* 堆排序
|
||||
* top-K 大(小)
|
||||
|
||||
|
||||
|
||||
# 堆存储结构
|
||||
|
||||
|
||||
`堆用数组来存储`,因为是一颗完全二叉树,i节点的父节点索引就是(i-1)/2, 左右子节点小标是 2i+1,2i+2。
|
||||
|
||||
堆的操作有:
|
||||
|
||||
* 建堆
|
||||
* 插入:都是插入到数组最后,然后再调整满足堆次序
|
||||
* 删除:删除总是发生在 A[0]处,也就是只删除根节点
|
||||
|
||||
这样难怪`堆`被称为 `优先队列`。 插入和删除分别在 数组尾部和头部,只是需要再次调整以满足堆次序。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
* 赫夫曼编码 Huffman
|
||||
|
||||
|
||||
## 二叉树
|
||||
|
||||
|
||||
|
||||
## [二叉查找树](2-二叉查找树/二叉查找树.md)
|
||||
|
||||
快速排序就是个二叉树的前序遍历,归并排序就是个二叉树的后序遍历
|
||||
|
||||
+8
-1
@@ -37,10 +37,17 @@
|
||||
# 图的存储结构
|
||||
|
||||
* 对象和指针
|
||||
* 矩阵
|
||||
* 邻接矩阵 (二维数组)
|
||||
* 邻接表
|
||||
|
||||
|
||||
图数据结构表示:
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
|
||||
## 图的操作
|
||||
|
||||
#### 遍历
|
||||
|
||||
+5
-28
@@ -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){
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user