update readme

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