From a2f9bc86ddb5f778a2cc2e9183f62037e2ff8a9d Mon Sep 17 00:00:00 2001
From: chenximing <243744327@qq.com>
Date: Tue, 17 Jul 2018 00:00:23 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 13 +-
.../\344\272\214\345\217\211\346\240\221.md" | 204 +++++-------------
.../\346\237\245\346\211\276.md" | 80 -------
3 files changed, 56 insertions(+), 241 deletions(-)
delete mode 100644 "\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\237\245\346\211\276.md"
diff --git a/README.md b/README.md
index 8c4310d..70b328c 100644
--- a/README.md
+++ b/README.md
@@ -10,13 +10,12 @@
## 数据结构与算法
-* [1.查找](数据结构与算法/查找.md)
-* [2.排序](数据结构与算法/排序.md)
-* [3.二叉树](数据结构与算法/二叉树.md)
-* [4.堆](数据结构与算法/堆.md)
-* [5.平衡查找树](数据结构与算法/平衡查找树.md)
-* [6.哈希表](数据结构与算法/哈希表.md)
-* [7.图](数据结构与算法/图.md)
+* [1.排序](数据结构与算法/排序.md)
+* [2.二叉树](数据结构与算法/二叉树.md)
+* [3.堆](数据结构与算法/堆.md)
+* [4.平衡查找树](数据结构与算法/平衡查找树.md)
+* [5.哈希表](数据结构与算法/哈希表.md)
+* [6.图](数据结构与算法/图.md)
* [算法题总结](数据结构与算法/算法题总结.md)
> 理论知识参考:
diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\344\272\214\345\217\211\346\240\221.md" "b/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\344\272\214\345\217\211\346\240\221.md"
index 22a9554..a59601a 100644
--- "a/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\344\272\214\345\217\211\346\240\221.md"
+++ "b/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\344\272\214\345\217\211\346\240\221.md"
@@ -1,22 +1,58 @@
-* [(前中后序)遍历](#前中后序遍历)
+* [两种特殊二叉树](#两种特殊二叉树)
+* [二叉树定理](#二叉树定理)
+* [前中后序遍历](#前中后序遍历)
* [递归版](#递归版)
* [迭代版](#迭代版)
- * [二叉树重建](#二叉树重建)
- * [根据前序、中序序列重建二叉树](#根据前序中序序列重建二叉树)
- * [根据前序、后序序列重建二叉树(不可行)](#根据前序后序序列重建二叉树不可行)
- * [根据中序、后序序列重建二叉树](#根据中序后序序列重建二叉树)
- * [二叉树序列化](#二叉树序列化)
-* [(广度优先)遍历](#广度优先遍历)
-* [路径](#路径)
-* [深度](#深度)
-* [理论知识](#理论知识)
- - [两种特殊二叉树](#两种特殊二叉树)
- - [二叉树定理](#二叉树定理)
+# 两种特殊二叉树
+* **满二叉树**:除叶子节点外的所有分支节点都含有2个非空子节点的二叉树
+* **完全二叉树**:除了最后一层,其余层都是“满”的,这样的二叉树是完全二叉树
+
+![](../pic/al-tree-1.png)
+
+
+
+
+# 二叉树定理
+
+### 1)任意二叉树度数为2节点的个数等于叶节点个数减1
+
+当只有1个节点时,度为0。每派生出1度,就会多出1个节点。派生出的度和派生出的节点数一定相等。那么就得出了总度数和节点总数的关系:
+
+`节点总数 = 总度数 + 1`
+
+设度数为2的节点数为`X2`,度数为1的节点数为`X1`,度数为0的节点数为`X0`。可以得出如下关系式:
+
+`X2+X1+X0=2X2+X1+1;`
+
+推出
+
+`X2=X0-1`;
+
+因此,**度数为2的节点个数等于叶节点数减1**
+
+### 2)满二叉树定理:非空满二叉树的叶节点数等于其分支节点数加1
+
+如果已知前一个结论,那么这个定理显然成立。下面分析如果不知道前一个结论,怎么证明
+
+对于只有1个节点的树,该定理成立。从这开始思考,每产生1个分支节点(度数为2)。叶子节点数也会加1。因为要产生一个分支节点,那么这个新的分支节点必然是原来的叶子节点,而新的分支节点又生成了2个新的叶子节点。因此叶子节点的总数先是减1然后加2,因此总数加1。因此,产生n个分支节点时,也产生了n个叶子节点,由于最初只有1个叶子节点,所以该定理成立
+
+### 3)一颗非空二叉树空子树的数目等于其节点数目加1
+
+考虑只有1个根节点的二叉树:它有2个空子树,1个节点,因此结论成立。从这里开始考虑,每产生1个节点。空子树便会先减1然后加2。就和上面结论中每多出1个分支节点,叶子节点的变化一样。因此在原来结论的基础上,由于空子树和节点等量增长。所以结论成立
+
+
+
+
+# 前中后序遍历
+
+* **前序**遍历:根->左->右
+* **中序**遍历:左->根->右
+* **后序**遍历:左->右->根
假设树节点的定义如下:
@@ -29,12 +65,6 @@ struct TreeNode {
};
```
-# (前中后序)遍历
-
-* 前序遍历:根->左->右
-* 中序遍历:左->根->右
-* 后序遍历:左->右->根
-
## 递归版
```c++
@@ -147,139 +177,5 @@ void postorderTraversalIteration(TreeNode *root)
对于后序遍历,由于其访问序列为:左->右->根。因此还有一种方法,可以按类似前序遍历的方式:根->右->左,然后对得到的结果反序
-> 相关题目:
-> * 剑指offer(8):二叉树的下一个节点
-> * 剑指offer(28):对称的二叉树
-
-## 二叉树重建
-
-### 根据前序、中序序列重建二叉树
-
-前序序列的特点:{首元素,左子树节点,右子树节点}
-中序序列的特点:{左子树节点,首元素,右子树节点}
-
-因此,可以根据前序序列的首元素创建根节点,然后遍历中序序列,找到首元素,递归处理左子树和右子树。函数返回(树或子树的)根节点,每个新创建节点分别将左右子节点设置为递归处理的返回节点
-
-**如何处理前序序列和中序序列不匹配等非法输入的情况?(throw std::exception("Invalid input"))**
-
-> 相关题目:剑指offer(7):重建二叉树
-
-### 根据前序、后序序列重建二叉树(不可行)
-
-后序序列中,根节点在末尾,前序序列中,根节点在首部,无法确定左右子树节点的范围,因此无法重建
-
-### 根据中序、后序序列重建二叉树
-
-和根据前序、中序序列重建的思想一样
-
-### 二叉树序列化
-
-序列中存储**空节点信息**(如使用‘$’)可以使用前序序列重建二叉树
-
-> 相关题目:
-> * 剑指offer(37):序列化二叉树
-
-# (广度优先)遍历
-
-**使用队列**
-
-```c++
-void depthTraversal(TreeNode *root)
-{
- deque d;
- if(root)
- d.push_back(root);
-
- TreeNode *curr;
- while(!d.empty()){
- curr = d.front();
- d.pop_front();
-
- cout << curr << " ";
-
- if(curr->left)
- d.push_back(curr->left);
- if(curr->right)
- d.push_back(curr->right);
- }
-}
-```
-
-> 相关题目:
-> * 剑指offer(32):不分行从上到下打印二叉树(题目一)
-> * 剑指offer(32):分行从上到下打印二叉树(题目二)
-> * 剑指offer(32):之字形打印二叉树(题目三)
-
-# 路径
-
-使用**辅助空间**保存路径(如vector)
-
-```c++
-/*
- * 函数获取到达节点dest的路径
- * dest是否为nullptr的检查应该在外层,因为该函数是一个递归的过程,一旦dest不为空,后续的递归都不会为空
- * 如果查找的节点不存在树中,可以通过path中的元素或者函数返回值判断
- */
-bool getPathCore(TreeNode *root,TreeNode *dest,vector &path)
-{
- if(!root)
- return false;
-
- //首先假设当前节点是所要查找路径中的一个节点,插入
- path.push_back(root);
-
- if(root == dest) //先判断当前节点是否是查找的节点(前序遍历)
- return true;
-
- bool find = false;
-
- //如果左子树中找到,则不会继续对右子树进行查找
- find = getPathCore(root->left,dest,path) || getPathCore(root->right,dest,path);
-
- //左子树或右子树中找到则直接返回(因为路径中肯定包含了当前节点,不返回会弹出)
- if(find)
- return find;
-
- //如果(左右)子树中都没找到,说明所要查找的路径不经过这个节点,弹出
- path.pop_back();
-
- return false;
-}
-```
-
-> 相关题目:
-> * 剑指offer(34):二叉树中和为某一值的(所有)路径
-
-# 深度
-
-```c++
-int TreeDepth(TreeNode* pRoot)
-{
- if(!pRoot)
- return 0;
-
- int depth1 = 1 + TreeDepth(pRoot->left);
- int depth2 = 1 + TreeDepth(pRoot->right);
-
- return depth1 > depth2 ? depth1 : depth2;
-}
-```
-
-> 相关题目:
-> * 剑指offer(55):二叉树的深度(题目一)
-> * 剑指offer(55):平衡二叉树AVL(题目二)
-
-# 理论知识
-
-## 两种特殊二叉树
-
-* **满二叉树**:除叶子节点外的所有分支节点都含有2个非空子节点的二叉树
-* **完全二叉树**:除了最后一层,其余层都是“满”的,这样的二叉树是完全二叉树
-
-![](../pic/al-tree-1.png)
-
-## 二叉树定理
-
-1. **满二叉树定理**:非空满二叉树的叶节点数等于其分支节点数加1
-2. 一颗非空二叉树空子树的数目等于其节点数目加1
-3. 任意二叉树度数为2节点的个数等于叶节点个数减1
\ No newline at end of file
+
+
\ No newline at end of file
diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\237\245\346\211\276.md" "b/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\237\245\346\211\276.md"
deleted file mode 100644
index b251e2a..0000000
--- "a/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\237\245\346\211\276.md"
+++ /dev/null
@@ -1,80 +0,0 @@
-* [二分查找](#二分查找)
- * [1.查找元素第一次出现的下标](#1查找元素第一次出现的下标)
- * [2.查找元素最后一次出现的下标](#2查找元素最后一次出现的下标)
-
-
-
-## 二分查找
-
-```c++
-int BinarySearch(vector data,int k){
- int sz = data.size();
- int l = 0,r = sz - 1;
- while(l <= r){
- int mid = (l + r) >> 1;
- if(data[mid] > k)
- r = mid - 1;
- else if(data[mid] < k)
- l = mid + 1;
- else
- return mid;
- }
-
- return -1;
-}
-```
-
-### 1.查找元素第一次出现的下标
-
-```c++
-int GetFirstK(vector data,int k){
- int sz = data.size();
- int l = 0,r = sz - 1;
- while(l <= r){
- int mid = (l + r) >> 1;
- if(data[mid] > k)
- r = mid - 1;
- else if(data[mid] < k)
- l = mid + 1;
- else{
- if(mid == 0 || data[mid - 1] != k)
- return mid;
- else
- r = mid - 1;
- }
- }
-
- return -1;
-}
-```
-
-### 2.查找元素最后一次出现的下标
-
-```c++
-int GetLastK(vector data,int k){
- int sz = data.size();
- int l = 0,r = sz - 1;
- while(l <= r){
- int mid = (l + r) >> 1;
- if(data[mid] > k)
- r = mid - 1;
- else if(data[mid] < k)
- l = mid + 1;
- else{
- if(mid == sz - 1 || data[mid + 1] != k)
- return mid;
- else
- l = mid + 1;
- }
- }
-
- return -1;
-}
-```
-
-> 相关题目:
-> * 剑指offer(11):[旋转数组的最小数字](https://www.nowcoder.com/practice/9f3231a991af4f55b95579b44b7a01ba?tpId=13&tqId=11159&tPage=1&rp=2&ru=%2Fta%2Fcoding-interviews&qru=%2Fta%2Fcoding-interviews%2Fquestion-ranking)
-> * Leetcode(33):[旋转后数组中查找数字](https://leetcode.com/problems/search-in-rotated-sorted-array/description/)
-> * 剑指offer(53):[数字在排序数组中出现的次数](https://www.nowcoder.com/practice/70610bf967994b22bb1c26f9ae901fa2?tpId=13&tqId=11190&tPage=2&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
-> * 剑指offer(53):[0~n-1中缺失的数字](code/53-2.md)
-> * 剑指offer(53):[数组中数值和下标相等的元素](code/53-3.md)
\ No newline at end of file