1. 深度优先遍历

1.1关于深度优先遍历

沿着树的深度遍历结点,尽可能深的搜索树的分支。如果当前的节点所在的边都被搜索过,就回溯到当前节点所在的那条边的起始节点。一直重复直到进行到发现源节点所有可达的节点为止。

1.2 算法实现

因为深度优先搜索算法是先访问根节点,接着遍历左子树再遍历右子树。为了方便,我们可以引入堆栈这个数据结构来帮我们快速解决DFS算法。因为栈是后进先出的结构,所以我们可以先将右子树压栈,再将左子树压栈,这样左子树就位于栈顶,可以保证先遍历左子树再遍历右子树。

我们通过下面的这个二叉树来简单的画图实现栈的深度优先搜索

二叉树的深度遍历和广度遍历 - 图1

图1

当我们在压栈时,必须确保该节点的左右子树都为空,如果不为空就需要先将它的右子树压栈,再将左子树压栈。等左右子树都压栈之后,才将结点压栈。

二叉树的深度遍历和广度遍历 - 图2

深度优先搜索

  1. void depthFirstTravel(Node* root){
  2. stack<Node *> nodeStack; //使用C++的STL标准模板库
  3. nodeStack.push(root);
  4. Node *node;
  5. while(!nodeStack.empty()){
  6. node = nodeStack.top();
  7. printf(format, node->data); //遍历根结点
  8. nodeStack.pop();
  9. if(node->rchild){
  10. nodeStack.push(node->rchild); //先将右子树压栈
  11. }
  12. if(node->lchild){
  13. nodeStack.push(node->lchild); //再将左子树压栈
  14. }
  15. }
  16. }

1.3 LeedCode上的一道简单DFS题
  1. Employee Importance
    题目主要的意思是求出该员工的重要程度,给了员工类包含ID、重要度、下属。计算该员工的重要度不单单计算自己,还得将下属的重要度一起计算上。

解决方案

  1. /*
  2. // Employee info
  3. class Employee {
  4. public:
  5. // It's the unique ID of each node.
  6. // unique id of this employee
  7. int id;
  8. // the importance value of this employee
  9. int importance;
  10. // the id of direct subordinates
  11. vector<int> subordinates;
  12. };
  13. */
  14. class Solution {
  15. public:
  16. unordered_map<int, Employee*> Emplmap;
  17. int getImportance(vector<Employee*> employees, int id) {
  18. for(int i=0;i<employees.size();i++)
  19. {
  20. Emplmap[employees[i]->id]=employees[i];
  21. }
  22. return DFS(Emplmap[id]);
  23. }
  24. int DFS(Employee* empl)
  25. {
  26. int sum = empl->importance;
  27. for(int i = 0;i<empl->subordinates.size();i++)
  28. {
  29. sum+=DFS(Emplmap[empl->subordinates[i]]);
  30. }
  31. return sum;
  32. }
  33. };

2. 广度优先遍历

2.1关于广度优先遍历

从根节点开始,沿着树的宽度遍历树的节点,直到所有节点都被遍历完为止。

2.2 算法实现

因为是按照一层一层遍历的,所以我们考虑引入队列这个数据结构帮助我们实现广度优先搜索算法。

二叉树的深度遍历和广度遍历 - 图3

树的层次遍历

  1. void breadthFirstTravel(Node* root){
  2. queue<Node *> nodeQueue; //使用C++的STL标准模板库
  3. nodeQueue.push(root);
  4. Node *node;
  5. while(!nodeQueue.empty()){
  6. node = nodeQueue.front();
  7. nodeQueue.pop();
  8. printf(format, node->data);
  9. if(node->lchild){
  10. nodeQueue.push(node->lchild); //先将左子树入队
  11. }
  12. if(node->rchild){
  13. nodeQueue.push(node->rchild); //再将右子树入队
  14. }
  15. }
  16. }

2.3 LeedCode上的一道简单广度搜索的题

给出一棵二叉树,返回其节点值从底向上的层次序遍历
解决方法:和上面的实现方式类似,只是最后需要把容器翻转过来。

  1. /**
  2. * Definition of TreeNode:
  3. * class TreeNode {
  4. * public:
  5. * int val;
  6. * TreeNode *left, *right;
  7. * TreeNode(int val) {
  8. * this->val = val;
  9. * this->left = this->right = NULL;
  10. * }
  11. * }
  12. */
  13. class Solution {
  14. /**
  15. * @param root : The root of binary tree.
  16. * @return : buttom-up level order a list of lists of integer
  17. */
  18. public:
  19. vector<vector<int>> levelOrderBottom(TreeNode *root) {
  20. vector<vector<int>> vec;
  21. if(root==NULL){
  22. return vec;
  23. }
  24. queue<TreeNode*> que;
  25. que.push(root);
  26. while(!que.empty()){
  27. int count=que.size();
  28. vector<int> vec_temp;
  29. while(count--){
  30. TreeNode* temp=que.front();
  31. que.pop();
  32. vec_temp.push_back(temp->val);
  33. if(temp->left){
  34. que.push(temp->left);
  35. }
  36. if(temp->right){
  37. que.push(temp->right);
  38. }
  39. }
  40. vec.push_back(vec_temp);
  41. }
  42. reverse(vec.begin(),vec.end());
  43. return vec;
  44. }
  45. };