当前位置:   article > 正文

二叉树_二叉搜索树查找最坏时间复杂度

二叉搜索树查找最坏时间复杂度

一、为什么要树结构?

不像数组、链表是线性的数据结构,树是一种分层的非线性数据结构
(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. struct TreeNode {
  2. int val;
  3. TreeNode *left;
  4. TreeNode *right;
  5. TreeNode(int x) : val(x), left(NULL), right(NULL) {}
  6. };

求二叉树的最小深度

最小深度是从根节点到最近的叶子节点的最短路径的节点数

【思路】:遍历一棵二叉树,从根部看起,查看它是否有左右结点。有五种情况
1.没有根节点,那结果就是0
2.有根节点,没有左右子树,结果为1
3.没有左子树,有右子树。把右子树看成一棵新的树。
4.没有右子树,有左子树。把左子树看成一棵新的树。
5.既有左子树,又有右子树。那就把左右子树分别都看成新的树,最后比较谁的最近叶子的路径短,就取哪边。

  1. //第一种方法层次遍历
  2. class Solution {
  3. public:
  4. int minDepth(TreeNode* root) {
  5. if(root==NULL)
  6. return 0;
  7. queue<TreeNode*>qtree;
  8. qtree.push(root);
  9. int num =1;
  10. while(!qtree.empty())
  11. {
  12. int cur=0;
  13. int last = qtree.size();
  14. while(cur < last)
  15. {
  16. TreeNode* temp = qtree.front();
  17. qtree.pop();
  18. if(temp->left==NULL&&temp->right==NULL)
  19. return num;
  20. else
  21. {
  22. if(temp->left)
  23. qtree.push(temp->left);
  24. if(temp->right)
  25. qtree.push(temp->right);
  26. }
  27. cur++;
  28. }
  29. num++;
  30. }
  31. return num;
  32. }
  33. };
  34. //第二种方法递归
  35. class Solution {
  36. public:
  37. int minDepth(TreeNode* root) {
  38. if(root==NULL)
  39. return 0;
  40. else if(root->left==NULL&&root->right==NULL)
  41. return 1;
  42. else if(root->left==NULL)
  43. return minDepth(root->right)+1;
  44. else if(root->right==NULL)
  45. return minDepth(root->left)+1;
  46. else
  47. return min(minDepth(root->right),minDepth(root->left))+1;
  48. }
  49. };

求二叉树节点的个数

第一种方法,暴力求解,时间复杂度O(N)

  1. class Solution {
  2. public:
  3. int countNodes(TreeNode* root) {
  4. if(!root)
  5. return 0;
  6. return countNodes(root->left)+countNodes(root->right)+1;
  7. }
  8. };

第二种方法,利用完全二叉树的性质,第h层的节点个数为2^h-1

  1. class Solution {
  2. public:
  3. int countNodes(TreeNode* root) {
  4. if(!root)
  5. return 0;
  6. int leftdepth=LeftTreedepth(root);
  7. int rightdepth=RightTreedepth(root);
  8. if(leftdepth==rightdepth)
  9. return (1<<leftdepth)-1;
  10. else
  11. return 1+countNodes(root->left)+countNodes(root->right);
  12. }
  13. int LeftTreedepth(TreeNode* root)
  14. {
  15. int depth=0;
  16. while(root)
  17. {
  18. depth++;
  19. root=root->left;
  20. }
  21. return depth;
  22. }
  23. int RightTreedepth(TreeNode* root)
  24. {
  25. int depth=0;
  26. while(root)
  27. {
  28. depth++;
  29. root=root->right;
  30. }
  31. return depth;
  32. }
  33. };

 

二叉树的前序遍历

给定一个二叉树,返回它的 前序 遍历。

 示例:

  1. 输入: [1,null,2,3]
  2. 1
  3. \
  4. 2
  5. /
  6. 3
  7. 输出: [1,2,3]

进阶: 递归算法很简单,你可以通过迭代算法完成吗?

第一种方法:递归法

  1. /**
  2. * Definition for a binary tree node.
  3. * struct TreeNode {
  4. * int val;
  5. * TreeNode *left;
  6. * TreeNode *right;
  7. * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
  8. * };
  9. */
  10. class Solution {
  11. public:
  12. vector<int> preorderTraversal(TreeNode* root) {
  13. vector<int> ret;
  14. preorder(root, ret);
  15. return ret;
  16. }
  17. void preorder(TreeNode* root, vector<int> &ret)
  18. {
  19. if(root)
  20. {
  21. ret.push_back(root->val);
  22. preorder(root->left, ret);
  23. preorder(root->right, ret);
  24. }
  25. }
  26. };

第二种方法:迭代法

  1. /**
  2. * Definition for a binary tree node.
  3. * struct TreeNode {
  4. * int val;
  5. * TreeNode *left;
  6. * TreeNode *right;
  7. * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
  8. * };
  9. */
  10. class Solution {
  11. public:
  12. vector<int> preorderTraversal(TreeNode* root) {
  13. vector<int> ret;
  14. stack<TreeNode *>pre;
  15. while(root || !pre.empty())
  16. {
  17. if(root)
  18. {
  19. ret.push_back(root->val);
  20. pre.push(root);
  21. root = root->left;
  22. }
  23. else
  24. {
  25. root = pre.top();
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/681273
推荐阅读
相关标签
  

闽ICP备14008679号