我要好offer之 二叉树大总结

一. 二叉树定义:二叉树具有天然的递归特性,凡是二叉树相关题,首先应该联想到递归

struct BinTreeNode {
    BinTreeNode* left;
    BinTreeNode* right;
    int          val;
    BinTreeNode(int value) : left(nullptr), right(nullptr), val(value) { }
};

二. 二叉树遍历

详见笔者博文:二叉树遍历大总结

  1 #include <iostream>
  2 #include <vector>
  3 #include <stack>
  4 using namespace std;
  5
  6 // 二叉树递归定义
  7 struct BinTreeNode {
  8     BinTreeNode* left;
  9     BinTreeNode* right;
 10     int          val;
 11     BinTreeNode(int value) : left(NULL), right(NULL), val(value) { }
 12 };
 13
 14 // 根据结点值构建二叉树
 15 BinTreeNode* BuildBinTree(BinTreeNode* root, int value) {
 16     if (root == NULL) {
 17         root = new BinTreeNode(value);  // 结点为空,new一个节点
 18     } else if (value <= root->val) {
 19         root->left = BuildBinTree(root->left, value);
 20     } else {
 21         root->right = BuildBinTree(root->right, value);
 22     }
 23     return root;
 24 }
 25
 26 // 先序遍历,递归
 27 void PreOrder(BinTreeNode* root) {
 28     if (root == NULL) return;
 29     std::cout << root->val << "-->";  // 访问节点
 30     PreOrder(root->left);
 31     PreOrder(root->right);
 32 }
 33
 34 // 先序遍历,非递归,栈版本
 35 void PreOrderStk(BinTreeNode* root) {
 36     if (root == NULL) return;
 37     std::stack<BinTreeNode*> stk;
 38     while (root != NULL || !stk.empty()) {
 39         while (root != NULL) {
 40             std::cout << root->val << "-->";  // 访问节点
 41             stk.push(root);
 42             root = root->left;  // 深度优先搜索到最左节点,然后回溯
 43         }
 44         BinTreeNode* cur = stk.top();
 45         stk.pop();
 46         root = cur->right;     // 转向右子树
 47     }
 48 }
 49
 50 // 先序遍历,非递归,非栈,Morris
 51 void PreOrderMorris(BinTreeNode* root) {
 52     if (root == NULL) return;
 53     BinTreeNode* prev = NULL;  // prev为刚刚访问过的节点
 54     BinTreeNode* cur = root;   // cur为正在访问的结点
 55     while (cur != NULL) {
 56         if (cur->left == NULL) {
 57             std::cout << cur->val << "-->";  // 访问节点
 58             prev = cur;   // 更新刚刚访问过的结点
 59             cur = cur->right;
 60         } else {
 61             BinTreeNode* node = cur->left;  // 前驱结点为 左子树最右下节点
 62             while (node->right != NULL && node->right != cur) {
 63                 node = node->right;
 64             }
 65             if (node->right == NULL) {   // 还没线索化,则建立线索
 66                 std::cout << cur->val << "-->";  // 仅这一行与中序不同
 67                 node->right = cur; // 建立线索
 68                 prev = cur;        // 更新刚刚访问过的结点
 69                 cur = cur->left;
 70             } else {
 71                 cur = cur->right;
 72                 node->right = NULL; // 已经线索化,则删除线索
 73             }
 74         }
 75     }
 76 }
 77
 78 // 中序遍历,递归
 79 void InOrder(BinTreeNode* root) {
 80     if (root == NULL) return;
 81     InOrder(root->left);
 82     std::cout << root->val << "-->";  // 访问节点
 83     InOrder(root->right);
 84 }
 85
 86 // 中序遍历,非递归,栈版本
 87 void InOrderStk(BinTreeNode* root) {
 88     if (root == NULL) return;
 89     std::stack<BinTreeNode*> stk;
 90     while (root != NULL || !stk.empty()) {
 91         while (root != NULL) {
 92             stk.push(root);
 93             root = root->left;  // 深度优先搜索到最左节点,然后回溯
 94         }
 95         BinTreeNode* cur = stk.top();
 96         stk.pop();
 97         std::cout << cur->val << "-->";  // 访问节点
 98         root = cur->right;     // 转向右子树
 99     }
100 }
101
102 // 中序遍历,非递归,非栈,Morris
103 void InOrderMorris(BinTreeNode* root) {
104     if (root == NULL) return;
105     BinTreeNode* prev = NULL;  // prev为刚刚访问过的结点
106     BinTreeNode* cur = root;   // cur为正在访问的结点
107     while (cur != NULL) {
108         if (cur->left == NULL) {
109             std::cout << cur->val << "-->";  // 访问节点
110             prev = cur;                      // 更新刚刚访问过的结点
111             cur = cur->right;
112         } else {
113             BinTreeNode* node = cur->left;  // 前驱结点为 左子树最右下节点
114             while (node->right != NULL && node->right != cur) {
115                 node = node->right;
116             }
117             if (node->right == NULL) {     // 还没线索化,则建立线索
118                 node->right = cur;   // 建立线索
119                 cur = cur->left;
120             } else {
121                 std::cout << cur->val << "-->";  // 已经线索化,则访问节点,并删除线索
122                 prev = cur;
123                 cur = cur->right;
124                 node->right = NULL;   // 删除线索
125             }
126         }
127     }
128 }
129
130 // 后序遍历,递归
131 void PostOrder(BinTreeNode* root) {
132     if (root == NULL) return;
133     PostOrder(root->left);
134     PostOrder(root->right);
135     std::cout << root->val << "-->";
136 }
137
138 // 后序遍历,非递归,栈版本
139 void PostOrderStk(BinTreeNode* root) {
140     if (root == NULL) return;
141     std::stack<BinTreeNode*> stk;
142     BinTreeNode* cur = root;
143     BinTreeNode* prev = NULL;
144     do {
145         while (cur != NULL) {
146             stk.push(cur);
147             cur = cur->left;
148         }
149         prev = NULL;
150         while (!stk.empty()) {
151             cur = stk.top();
152             stk.pop();
153             if (cur->right == prev) {
154                 std::cout << cur->val << "-->";
155                 prev = cur;
156             } else {
157                 stk.push(cur);
158                 cur = cur->right;
159                 break;
160             }
161         }
162     } while (!stk.empty());
163 }
164
165 // 层次遍历,递归版
166 void LevelOrder(BinTreeNode* root, int level, std::vector<std::vector<int>>& res) {
167     if (root == NULL) return;
168     if (level > res.size()) {
169         res.push_back(std::vector<int>());
170     }
171     res.at(level - 1).push_back(root->val);
172     LevelOrder(root->left, level + 1, res);
173     LevelOrder(root->right, level + 1, res);
174 }
175 std::vector<std::vector<int>> LevelOrderHelp(BinTreeNode* root) {
176     std::vector<std::vector<int>> res;
177     LevelOrder(root, 1, res);
178     return res;
179 }
180
181 // 层次遍历,非递归,队列版
182 void LevelOrderQueue(BinTreeNode* root) {
183     if (root == NULL) return;
184     std::deque<BinTreeNode*> dequeTreeNode;
185     dequeTreeNode.push_back(root);
186     while (!dequeTreeNode.empty()) {
187         BinTreeNode* cur = dequeTreeNode.front();
188         dequeTreeNode.pop_front();
189         std::cout << cur->val << "-->"; // 访问节点
190         if (cur->left  != NULL) dequeTreeNode.push_back(cur->left);
191         if (cur->right != NULL) dequeTreeNode.push_back(cur->right);
192     }
193 }
194
195 int main() {
196     // your code goes here
197     std::vector<int> num = {6, 2, 7, 1, 4, 9, 3, 5, 8};
198     BinTreeNode* root = nullptr;
199     for (auto val : num) {
200         root = BuildBinTree(root, val);
201     }
202     std::cout << "1:PreOrder:" << std::endl;
203     std::cout << "\t PreOrder:" ;
204     PreOrder(root);
205     std::cout << std::endl;
206     std::cout << "\t PreOrderStk:";
207     PreOrderStk(root);
208     std::cout << std::endl;
209     std::cout << "\t PreOrderMorris:";
210     PreOrderMorris(root);
211     std::cout << std::endl;
212
213     std::cout << "2:InOrder:" << std::endl;
214     std::cout << "\t InOrder:";
215     InOrder(root);
216     std::cout << std::endl;
217     std::cout << "\t InOrderStk:";
218     InOrderStk(root);
219     std::cout << std::endl;
220     std::cout << "\t InOrderMorris:";
221     InOrderMorris(root);
222     std::cout << std::endl;
223
224     std::cout << "3:PostOrder:" << std::endl;
225     std::cout << "\t PostOrder:";
226     PostOrder(root);
227     std::cout << std::endl;
228     std::cout << "\t PostOrderStk:";
229     PostOrderStk(root);
230     std::cout << std::endl;
231
232     std::cout << "4:LevelOrder:" << std::endl;
233     std::cout << "\t LevelOrder:";
234     LevelOrderQueue(root);
235     std::cout << std::endl;
236     return 0;
237 }

三. 二叉树构建

1. 先序序列和中序序列构建一颗二叉树  中序序列和后序序列构建一棵二叉树

2. 有序数组/链表 构建一颗二叉查找树BST

四. 二叉树判断

1. 判断二叉查找树BST

2. 判断平衡二叉树

3. 判断对称二叉树

4. 判断相同二叉树

我要好offer之 二叉树大总结,布布扣,bubuko.com

时间: 2024-10-17 11:59:23

我要好offer之 二叉树大总结的相关文章

我要好offer之 链表大总结

单链表是一种递归结构,可以将单链表看作特殊的二叉树(我把它叫做一叉树) 单链表的定义: /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ 1. O(1)时间删除结点 ListNode* DeleteNode(ListNode* pHead, ListNode* dele

我要好offer之 搜索算法大总结

1. 二分搜索 详见笔者博文:二分搜索的那些事儿,非常全面 2. 矩阵二分搜索 (1) 矩阵每行递增,且下一行第一个元素大于上一个最后一个元素 (2) 矩阵每行递增,且每列也递增 3. DFS 深度优先搜索 适用场景: (1) 输入数据:如果是 递归数据结构(如单链表.二叉树),则一定可以使用DFS (2) 求解目标:必须走到最深处(例如二叉树,必须走到叶子节点)才能得到一个解,这种情况一般适合用DFS 思考步骤: (1) DFS最常见的3个问题:求可行解的总数.求任一个可行解.求所有可行解 (

我要好offer之 C++大总结

0. Google C++编程规范 英文版:http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml 中文版:http://zh-google-styleguide.readthedocs.org/en/latest/google-cpp-styleguide/contents/ 1. C++函数的林林总总 2. Effective C++学习笔记 (1) 习惯c++,const特性 (2) 构造.析构.赋值.copy and

我要好offer之 排序算法大总结

1. 插入排序 (1) 直接插入排序 void StraightInsertionSort(std::vector<int>& num) { if (num.size() == 0 || num.size() == 1) return; for (int i = 1; i < num.size(); ++i) { int tmp = num.at(i); int j = i - 1; for (; j >= 0 && num.at(j) > tmp;

【剑指offer】二叉树的镜像

转载请注明出处:http://blog.csdn.net/ns_code/article/details/25915971 题目描述: 输入一个二叉树,输出其镜像. 输入: 输入可能包含多个测试样例,输入以EOF结束.对于每个测试案例,输入的第一行为一个整数n(0<=n<=1000,n代表将要输入的二叉树节点的个数(节点从1开始编号).接下来一行有n个数字,代表第i个二叉树节点的元素的值.接下来有n行,每行有一个字母Ci.Ci='d'表示第i个节点有两子孩子,紧接着是左孩子编号和右孩子编号.C

我要好offer之 str/mem系列手写代码

1. str*系列手写代码 a. 一定要注意末尾'\0'的处理,切记切记 b. 一定要对输入做有效性判断,多用断言就是了 int Strlen(const char* str) { assert(str != NULL); const char* tmp = str; while (*tmp != '\0') { ++tmp; } return tmp - str; } char* Strcpy(char* dst, const char* src) { assert(dst != NULL &

剑指OFFER之二叉树的镜像(九度OJ1521)

题目描述: 输入一个二叉树,输出其镜像. 输入: 输入可能包含多个测试样例,输入以EOF结束.对于每个测试案例,输入的第一行为一个整数n(0<=n<=1000,n代表将要输入的二叉树节点的个数(节点从1开始编号).接下来一行有n个数字,代表第i个二叉树节点的元素的值.接下来有n行,每行有一个字母Ci.Ci='d'表示第i个节点有两子孩子,紧接着是左孩子编号和右孩子编号.Ci='l'表示第i个节点有一个左孩子,紧接着是左孩子的编号.Ci='r'表示第i个节点有一个右孩子,紧接着是右孩子的编号.C

剑指offer (19) 二叉树镜像 对称二叉树

题目: 输入一个二叉树,输出其镜像. BinTreeNode* ReverseTree(BinTreeNode* pRoot) { if (pRoot == NULL) return NULL; BinTreeNode* pLeftReverse = ReverseTree(pRoot->left); BinTreeNode* pRightReverse = ReverseTree(pRoot->right); pRoot->left = pRightReverse; pRoot->

剑指offer (39) 二叉树深度

题目:输入一棵二叉树的根节点,求该树的深度 题解分析: 二叉树具有天然的递归性,首先应该想递归解法 /** * Definition for binary tree * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: int maxDept