前言:
#include <queue> #include <vector> #include <stack> #include <algorithm> using namespace std; struct TreeNode{ int val; TreeNode* left; TreeNode* right; TreeNode(int n) :val(n), left(nullptr), right(nullptr){} }; //1、求二叉树中的节点个数 //暴力递归法用于普通的二叉树 int countNodes(TreeNode* root) { if (root == NULL) return 0; return countNodes(root->left) + countNodes(root->right) + 1; } //对于完全二叉树可以使用公式2^h-1 int getleft(TreeNode* root) { int count = 0; while (root->left != NULL) { root = root->left; count++; } return count; } int getright(TreeNode* root) { int count = 0; while (root->right != NULL) { root = root->right; count++; } return count; } int countNodes2(TreeNode* root) { if (root == NULL) return 0; int leftcount = getleft(root)+1; int rightcount = getright(root)+1; if (leftcount == rightcount) return (2 << (leftcount-1)) - 1;//这里 else return countNodes2(root->left) + countNodes2(root->right) + 1; } //2、求二叉树的深度 //2.1求二叉树的最大深度 int maxDepth(TreeNode* root) { if (root == NULL) return 0; int maxLeft = maxDepth(root->left); int maxRight = maxDepth(root->right); return maxLeft > maxRight ? (maxLeft + 1) : (maxRight + 1); } //2.2求二叉树的最小深度 int minDepth(TreeNode* root) { if (root == NULL) return 0; if (root->left == NULL&&root->right == NULL) return 1; int left = minDepth(root->left); int right = minDepth(root->right); if (root->left == NULL) return right + 1; if (root->right == NULL) return left + 1; return left > right ? (right + 1) : (left + 1); } int minDepth2(TreeNode* root) { queue<pair<TreeNode*, int> >q; if (root == NULL) return 0; q.push(make_pair(root, 1)); while (!q.empty()) { pair<TreeNode*, int> cur = q.front(); q.pop(); if (cur.first->left == NULL&&cur.first->right == NULL)//遇到第一个叶子节点的时候返回 return cur.second; if (cur.first->left) q.push(make_pair(cur.first->left,cur.second+1)); if (cur.first->right) q.push(make_pair(cur.first->right, cur.second + 1)); } } //3、前中后序遍历 //3.1 递归遍历 vector<int> vec; vector<int> inorderTraversal(TreeNode* root) { if (root == NULL) return vec; inorderTraversal(root->left); vec.push_back(root->val); inorderTraversal(root->right); return vec; } vector<int> preorderTraversal(TreeNode* root) { if (root == NULL) return vec; vec.push_back(root->val); preorderTraversal(root->left); preorderTraversal(root->right); return vec; } vector<int> postorderTraversal(TreeNode* root) { if (root == NULL) return vec; postorderTraversal(root->left); postorderTraversal(root->right); vec.push_back(root->val); return vec; } //3.2非递归版本 vector<int> inorderTraversal(TreeNode* root) { stack<TreeNode*> s; TreeNode* temp = root; while (temp != NULL|| !s.empty()) { while (temp != NULL) { s.push(temp); temp = temp->left; } if (!s.empty()) { temp = s.top(); s.pop(); vec.push_back(temp->val); temp = temp->right; } } return vec; } vector<int> preorderTraversal(TreeNode* root) { stack<TreeNode*> s; TreeNode* temp = root; while (temp || !s.empty()) { while (temp != NULL) { vec.push_back(temp->val); s.push(temp); temp = temp->left; } if (!s.empty()) { temp = s.top(); temp = temp->right; s.pop(); } } return vec; } vector<int> postorderTraversal(TreeNode* root) { if (root == NULL) return vec; return vec; } //4、分层遍历二叉树 //4.1 vector<vector<int>> levelOrder(TreeNode* root) { vector<TreeNode*> q; vector<vector<int> >res; if (root != NULL) { q.push_back(root); int cur = 0; int last = 1; while (cur < q.size()) { last = q.size(); vector<int> vec; while (cur < last) { vec.push_back(q[cur]->val); if (q[cur]->left) q.push_back(q[cur]->left); if (q[cur]->right) q.push_back(q[cur]->right); cur++; } res.push_back(vec); } } return res; } //4.2之字形打印二叉树 vector<vector<int>> zigzagLevelOrder(TreeNode* root) { vector<TreeNode*> q; vector<vector<int> >res; if (root != NULL) { q.push_back(root); int cur = 0; int last = 1; int row = 1; while (cur < q.size()) { last = q.size(); vector<int> vec; while (cur < last) { vec.push_back(q[cur]->val); if (q[cur]->left) q.push_back(q[cur]->left); if (q[cur]->right) q.push_back(q[cur]->right); cur++; } if (row % 2 == 0) { reverse(vec.begin(), vec.end()); } row++; res.push_back(vec); } } return res; } //5、将二叉查找树变为有序的双向链表 //6、求二叉树第k层节点个数 int numOfKthLevel(TreeNode* root, int k) { if (root == NULL || k < 1) return 0; if (k == 1) return 1; int numleft = numOfKthLevel(root->left, k - 1); int numright = numOfKthLevel(root->right, k - 1); return numleft + numright; } //7、求二叉树中叶子节点的个数 int numOfLeaf(TreeNode* root) { if (root == NULL) return 0; bool isleaf = root->left == NULL&&root->right == NULL; if (isleaf) return 1; int numleft = numOfLeaf(root->left); int numright = numOfLeaf(root->right); return numleft + numright; } //8、判断两个二叉树的结构是否相同 bool isSameTree(TreeNode* p, TreeNode* q) { if (p == NULL&&q == NULL) return true; if ((p == NULL&&q != NULL) || (p != NULL&&q == NULL)) return false; if (p->val != q->val) return false; else { bool l = isSameTree(p->left, q->left); bool r = isSameTree(p->right, q->right); if (l&&r) return true; else return false; } } //9、判断二叉树是否为平衡二叉树 bool isBalanced(TreeNode* root) { if (root == NULL) return true; int* depth = 0; return isBalanced2(root, depth); } bool isBalanced2(TreeNode* root, int *depth) { if (root == NULL) { depth = 0; return true; } int nleft, nright; bool rl = isBalanced2(root->left, &nleft); bool rr = isBalanced2(root->right, &nright); if (rl&&rr) { int diff = nleft - nright; if (diff >= -1 && diff <= 1) { *depth = nleft > nright ? (nleft + 1) : (nright + 1); return true; } } return false; } //10、求二叉树的镜像 TreeNode* invertTree(TreeNode* root) { if (root == NULL) return NULL; TreeNode* temp = root->left; root->left = root->right; root->right = temp; root->left = invertTree(root->left); root->right = invertTree(root->right); return root; } //10.2判断一个树是否对称 bool isSymmetric(TreeNode* root) { if (root == NULL) return true; return isSymmetric2(root->left, root->right); } bool isSymmetric2(TreeNode* root1, TreeNode* root2) { if (root1 == NULL&&root2 == NULL) return true; if ((root1 != NULL&&root2 == NULL) || (root1 == NULL&&root2 != NULL)) return false; if (root1->val != root2->val) return false; bool l = isSymmetric2(root1->left, root2->right); bool r = isSymmetric2(root1->right, root2->left); return l&&r; } //11、求二叉树两个节点的最低公共祖先节点 //12、求二叉树中节点的最大距离 //13、由前序遍历和中序遍历重建二叉树 typedef vector<int>::iterator Iter; TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { if (preorder.size() == 0 || inorder.size() == 0||preorder.size()!=inorder.size()) return NULL; return buildTree2(preorder.begin(), preorder.end(), inorder.begin(), inorder.end()); } TreeNode* buildTree2(Iter pbegin, Iter pend, Iter ibegin, Iter iend) { if (pbegin == pend || ibegin == iend) return NULL; TreeNode* root = new TreeNode(*pbegin); auto iroot = find(ibegin, iend, *pbegin); int leftlength = iroot - ibegin; root->left = buildTree2(pbegin+1,pbegin+leftlength+1, ibegin,iroot); root->right = buildTree2(pbegin + leftlength + 1,pend, iroot+1,iend); return root; } //由后序和中序重建二叉树 typedef vector<int>::iterator Iter; TreeNode* buildTree2(Iter pbegin, Iter pend, Iter ibegin, Iter iend) { if (pbegin == pend || ibegin == iend) return NULL; TreeNode* root = new TreeNode(*(pend - 1)); auto iroot = find(ibegin, iend, *(pend - 1)); int leftlength = iroot - ibegin; root->left = buildTree2(pbegin, pbegin + leftlength, ibegin, iroot); root->right = buildTree2(pbegin + leftlength, pend - 1, iroot + 1, iend); return root; } TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) { if (postorder.size() == 0 || inorder.size() == 0 || postorder.size() != inorder.size()) return NULL; return buildTree2(postorder.begin(), postorder.end(), inorder.begin(), inorder.end()); } //14、判断二叉树是否为完全二叉树 //15、将有序数组组成二叉查找树 TreeNode* sortedArrayToBST(vector<int>& nums) { if (nums.empty()) return NULL; TreeNode* root = new TreeNode(nums[nums.size() / 2]); vector<int> pre(nums.begin(), nums.begin() + nums.size() / 2); vector<int> last(nums.begin() + nums.size() / 2 + 1, nums.end()); root->left = sortedArrayToBST(pre); root->right = sortedArrayToBST(last); return root; }
一、为什么要树结构?
不像数组、链表是线性的数据结构,树是一种分层的非线性数据结构
(1)使用树的一个原因是:我们需要存储有分层关系的信息(比如说文件系统)
(2)另外一个是(BST):当把树建成有一定的形式的树可以方便数据的查找(对于平衡的树,查找时间复杂度为O(logn))。
(3)同理对于这样一个树(AVL/红黑树):他们的插入和删除的时间复杂度是(O(logn))
(4)相对于数组来说,树使用指针操作,可以动态的扩展节点。
二、二叉树的BFS和DFS
1、一个树典型的以两种方式进行遍历:
- 广度优先遍历(或者层序遍历)
- 深度优先遍历
- 中序遍历
- 前序遍历
- 后序遍历
2、四种遍历方式的比较
(1)时间复杂度上,上面四种遍历方式都需要O(n)的时间,因为他们都遍历了每一个node
(2)空间复杂度上,
- 对于BFS来说空间复杂度为O(w)其中w是二叉树的最大宽度,在层序遍历的时候,使用队列依次存储不同层次的nodes
- 对于DFS来说空间复杂度是O(h)其中h是二叉树的最大高度,在深度遍历的时候,使用stack来存储他们的祖先nodes
3、如何选择一种遍历方式?
平衡二叉树的高度为O(logn),最坏的情况下出现倾斜树的时候成为O(n)
- 额外的空间是一个选择的标准
- DFS一般使用的是递归的方法,递归方法的函数调用的开销也是一个因素
- 最重要的是:BFS总是从根节点开始,而DFS更倾向于从叶子节点开始,所以如果我们的问题是寻找查找离根节点很近的话我们要用BFS,反之使用DFS。
三、二叉树的一些特性
(1)第i层上的节点个数是2^(i-1),也就是i层上的节点个数是i-1层上的2倍
(2)第i层之前的所有节点个数是2^i-1;(1+2+4+7+2^(i-1))
(3)如果二叉树也有N个节点,最小可能的高度或者最小的层数是(log2(N+1))
(4)一个二叉树有L个叶子节点那么至少有log2L+1层
(5)二叉树中度为0的节点要比度为2的节点多一个
完全二叉树:
满二叉树(节点只有度为0和度为2,
这里和我之前理解不同!!)
完美二叉树
四、一些习题和代码
注解
1、求二叉树中的节点个数(222)
2、求二叉树的深度(104)
求二叉树的最小深度(111)
3、前中后序遍历(94/144/145)
4、分层遍历二叉树(102/107)
之字形遍历(103)
5、将二叉查找树变为有序的双向链表(114)
6、求二叉树第k层节点个数
7、求二叉树中叶子节点的个数
8、判断两个二叉树的结构是否相同(100)
9、判断二叉树是否为平衡二叉树(110)
10、求二叉树的镜像(226)
判断二叉树是否对称(101)
- <span style=“line-height: 1.5; font-family: ‘Courier New’; background-color: inherit;”>11、求二叉树两个节点的最低公共祖先节点(236)</span>
<span style="line-height: 1.5; font-family: 'Courier New'; background-color: inherit;">11、求二叉树两个节点的最低公共祖先节点(236)</span>
12、求二叉树中节点的最大距离
13、由前序遍历和中序遍历重建二叉树(105)
由中序和后序遍历重建二叉树(106)
14、判断二叉树是否为完全二叉树()
15、将一个有序数组转化为二叉查找树(108)
- #include <iostream>
- #include <queue>
- #include <vector>
- #include <stack>
- #include <algorithm>
- using namespace std;
- struct TreeNode{
- int val;
- TreeNode* left;
- TreeNode* right;
- TreeNode(int n) :val(n), left(nullptr), right(nullptr){}
- };
- //1、求二叉树中的节点个数
- //暴力递归法用于普通的二叉树
- int countNodes(TreeNode* root)
- {
- if (root == NULL)
- return 0;
- return countNodes(root->left) + countNodes(root->right) + 1;
- }
- //对于完全二叉树可以使用公式2^h-1
- int getleft(TreeNode* root)
- {
- int count = 0;
- while (root->left != NULL)
- {
- root = root->left;
- count++;
- }
- return count;
- }
- int getright(TreeNode* root)
- {
- int count = 0;
- while (root->right != NULL)
- {
- root = root->right;
- count++;
- }
- return count;
- }
- int countNodes2(TreeNode* root)
- {
- if (root == NULL)
- return 0;
- int leftcount = getleft(root)+1;
- int rightcount = getright(root)+1;
- if (leftcount == rightcount)
- return (2 << (leftcount-1)) - 1;//这里
- else
- return countNodes2(root->left) + countNodes2(root->right) + 1;
- }
- //2、求二叉树的深度
- //2.1求二叉树的最大深度
- int maxDepth(TreeNode* root)
- {
- if (root == NULL)
- return 0;
- int maxLeft = maxDepth(root->left);
- int maxRight = maxDepth(root->right);
- return maxLeft > maxRight ? (maxLeft + 1) : (maxRight + 1);
- }
- //2.2求二叉树的最小深度
- int minDepth(TreeNode* root)
- {
- if (root == NULL)
- return 0;
- if (root->left == NULL&&root->right == NULL)
- return 1;
- int left = minDepth(root->left);
- int right = minDepth(root->right);
- if (root->left == NULL)
- return right + 1;
- if (root->right == NULL)
- return left + 1;
- return left > right ? (right + 1) : (left + 1);
- }
- int minDepth2(TreeNode* root)
- {
- queue<pair<TreeNode*, int> >q;
- if (root == NULL)
- return 0;
- q.push(make_pair(root, 1));
- while (!q.empty())
- {
- pair<TreeNode*, int> cur = q.front();
- q.pop();
- if (cur.first->left == NULL&&cur.first->right == NULL)//遇到第一个叶子节点的时候返回
- return cur.second;
- if (cur.first->left)
- q.push(make_pair(cur.first->left,cur.second+1));
- if (cur.first->right)
- q.push(make_pair(cur.first->right, cur.second + 1));
- }
- }
- //3、前中后序遍历
- //3.1 递归遍历
- vector<int> vec;
- vector<int> inorderTraversal(TreeNode* root) {
- if (root == NULL)
- return vec;
- inorderTraversal(root->left);
- vec.push_back(root->val);
- inorderTraversal(root->right);
- return vec;
- }
- vector<int> preorderTraversal(TreeNode* root) {
- if (root == NULL)
- return vec;
- vec.push_back(root->val);
- preorderTraversal(root->left);
- preorderTraversal(root->right);
- return vec;
- }
- vector<int> postorderTraversal(TreeNode* root) {
- if (root == NULL)
- return vec;
- postorderTraversal(root->left);
- postorderTraversal(root->right);
- vec.push_back(root->val);
- return vec;
- }
- //3.2非递归版本
- vector<int> inorderTraversal(TreeNode* root) {
- stack<TreeNode*> s;
- TreeNode* temp = root;
- while (temp != NULL|| !s.empty())
- {
- while (temp != NULL)
- {
- s.push(temp);
- temp = temp->left;
- }
- if (!s.empty())
- {
- temp = s.top();
- s.pop();
- vec.push_back(temp->val);
- temp = temp->right;
- }
- }
- return vec;
- }
- vector<int> preorderTraversal(TreeNode* root) {
- stack<TreeNode*> s;
- TreeNode* temp = root;
- while (temp || !s.empty())
- {
- while (temp != NULL)
- {
- vec.push_back(temp->val);
- s.push(temp);
- temp = temp->left;
- }
- if (!s.empty())
- {
- temp = s.top();
- temp = temp->right;
- s.pop();
- }
- }
- return vec;
- }
- vector<int> postorderTraversal(TreeNode* root) {
- if (root == NULL)
- return vec;
- return vec;
- }
- //4、分层遍历二叉树
- //4.1
- vector<vector<int>> levelOrder(TreeNode* root) {
- vector<TreeNode*> q;
- vector<vector<int> >res;
- if (root != NULL)
- {
- q.push_back(root);
- int cur = 0;
- int last = 1;
- while (cur < q.size())
- {
- last = q.size();
- vector<int> vec;
- while (cur < last)
- {
- vec.push_back(q[cur]->val);
- if (q[cur]->left)
- q.push_back(q[cur]->left);
- if (q[cur]->right)
- q.push_back(q[cur]->right);
- cur++;
- }
- res.push_back(vec);
- }
- }
- return res;
- }
- //4.2之字形打印二叉树
- vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
- vector<TreeNode*> q;
- vector<vector<int> >res;
- if (root != NULL)
- {
- q.push_back(root);
- int cur = 0;
- int last = 1;
- int row = 1;
- while (cur < q.size())
- {
- last = q.size();
- vector<int> vec;
- while (cur < last)
- {
- vec.push_back(q[cur]->val);
- if (q[cur]->left)
- q.push_back(q[cur]->left);
- if (q[cur]->right)
- q.push_back(q[cur]->right);
- cur++;
- }
- if (row % 2 == 0)
- {
- reverse(vec.begin(), vec.end());
- }
- row++;
- res.push_back(vec);
- }
- }
- return res;
- }
- //5、将二叉查找树变为有序的双向链表
- //6、求二叉树第k层节点个数
- int numOfKthLevel(TreeNode* root, int k)
- {
- if (root == NULL || k < 1)
- return 0;
- if (k == 1)
- return 1;
- int numleft = numOfKthLevel(root->left, k - 1);
- int numright = numOfKthLevel(root->right, k - 1);
- return numleft + numright;
- }
- //7、求二叉树中叶子节点的个数
- int numOfLeaf(TreeNode* root)
- {
- if (root == NULL)
- return 0;
- bool isleaf = root->left == NULL&&root->right == NULL;
- if (isleaf)
- return 1;
- int numleft = numOfLeaf(root->left);
- int numright = numOfLeaf(root->right);
- return numleft + numright;
- }
- //8、判断两个二叉树的结构是否相同
- bool isSameTree(TreeNode* p, TreeNode* q) {
- if (p == NULL&&q == NULL)
- return true;
- if ((p == NULL&&q != NULL) || (p != NULL&&q == NULL))
- return false;
- if (p->val != q->val)
- return false;
- else
- {
- bool l = isSameTree(p->left, q->left);
- bool r = isSameTree(p->right, q->right);
- if (l&&r)
- return true;
- else return false;
- }
- }
- //9、判断二叉树是否为平衡二叉树
- bool isBalanced(TreeNode* root) {
- if (root == NULL)
- return true;
- int* depth = 0;
- return isBalanced2(root, depth);
- }
- bool isBalanced2(TreeNode* root, int *depth)
- {
- if (root == NULL)
- {
- depth = 0;
- return true;
- }
- int nleft, nright;
- bool rl = isBalanced2(root->left, &nleft);
- bool rr = isBalanced2(root->right, &nright);
- if (rl&&rr)
- {
- int diff = nleft - nright;
- if (diff >= -1 && diff <= 1)
- {
- *depth = nleft > nright ? (nleft + 1) : (nright + 1);
- return true;
- }
- }
- return false;
- }
- //10、求二叉树的镜像
- TreeNode* invertTree(TreeNode* root) {
- if (root == NULL)
- return NULL;
- TreeNode* temp = root->left;
- root->left = root->right;
- root->right = temp;
- root->left = invertTree(root->left);
- root->right = invertTree(root->right);
- return root;
- }
- //10.2判断一个树是否对称
- bool isSymmetric(TreeNode* root) {
- if (root == NULL)
- return true;
- return isSymmetric2(root->left, root->right);
- }
- bool isSymmetric2(TreeNode* root1, TreeNode* root2)
- {
- if (root1 == NULL&&root2 == NULL)
- return true;
- if ((root1 != NULL&&root2 == NULL) || (root1 == NULL&&root2 != NULL))
- return false;
- if (root1->val != root2->val)
- return false;
- bool l = isSymmetric2(root1->left, root2->right);
- bool r = isSymmetric2(root1->right, root2->left);
- return l&&r;
- }
- //11、求二叉树两个节点的最低公共祖先节点
- //12、求二叉树中节点的最大距离
- //13、由前序遍历和中序遍历重建二叉树
- typedef vector<int>::iterator Iter;
- TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
- if (preorder.size() == 0 || inorder.size() == 0||preorder.size()!=inorder.size())
- return NULL;
- return buildTree2(preorder.begin(), preorder.end(), inorder.begin(), inorder.end());
- }
- TreeNode* buildTree2(Iter pbegin, Iter pend, Iter ibegin, Iter iend)
- {
- if (pbegin == pend || ibegin == iend)
- return NULL;
- TreeNode* root = new TreeNode(*pbegin);
- auto iroot = find(ibegin, iend, *pbegin);
- int leftlength = iroot - ibegin;
- root->left = buildTree2(pbegin+1,pbegin+leftlength+1, ibegin,iroot);
- root->right = buildTree2(pbegin + leftlength + 1,pend, iroot+1,iend);
- return root;
- }
- //由后序和中序重建二叉树
- typedef vector<int>::iterator Iter;
- TreeNode* buildTree2(Iter pbegin, Iter pend, Iter ibegin, Iter iend)
- {
- if (pbegin == pend || ibegin == iend)
- return NULL;
- TreeNode* root = new TreeNode(*(pend - 1));
- auto iroot = find(ibegin, iend, *(pend - 1));
- int leftlength = iroot - ibegin;
- root->left = buildTree2(pbegin, pbegin + leftlength, ibegin, iroot);
- root->right = buildTree2(pbegin + leftlength, pend - 1, iroot + 1, iend);
- return root;
- }
- TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
- if (postorder.size() == 0 || inorder.size() == 0 || postorder.size() != inorder.size())
- return NULL;
- return buildTree2(postorder.begin(), postorder.end(), inorder.begin(), inorder.end());
- }
- //14、判断二叉树是否为完全二叉树
- //15、将有序数组组成二叉查找树
- TreeNode* sortedArrayToBST(vector<int>& nums) {
- if (nums.empty())
- return NULL;
- TreeNode* root = new TreeNode(nums[nums.size() / 2]);
- vector<int> pre(nums.begin(), nums.begin() + nums.size() / 2);
- vector<int> last(nums.begin() + nums.size() / 2 + 1, nums.end());
- root->left = sortedArrayToBST(pre);
- root->right = sortedArrayToBST(last);
- return root;
- }
#include <iostream>
参考文章:http://blog.csdn.net/luckyxiaoqiang/article/details/7518888#topic2
以及一些leetcode题目的博客