哈希表在遍历链式结构中的运用--以链表和二叉树的遍历为例

Posted C_YCBX Py_YYDS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了哈希表在遍历链式结构中的运用--以链表和二叉树的遍历为例相关的知识,希望对你有一定的参考价值。

题目一:在二叉树中遍历的运用

题目解析

关于如何找到和某个结点距离为 k 的结点,我们很快可以想到用递归实现,但是很快意识到这种方式只能求出到根节点的距离为 k 的所有结点,所以如果以这种方式只能求取在 target 下面距离的结点,而无法向上遍历,那么该如何实现向上遍历呢?

  • 答案是----哈希表

我们根据哈希表存储每个结点的父节点,这样我们只需要在遍历二叉树时进行特殊的判断,即可实现向上遍历而不回头。

  • 如何设计这样一个递归函数?—在参数中添加 from 参数记录上一个遍历而来的结点,方便判断当前的遍历方向,如果 from 记录的是当前结点的父节点,则它当前的遍历方向是向下的,否则就是正在向上遍历,由于向上遍历的时候走左右某一条路可能又回到了之前的地方,所以需要判断 root->left or root->right != from

好了,讲到这应该大家都理解了,这下自己写代码应该也能写了,剩下的就是处理遍历的细节问题,由于我们搜索的是某个具体的根节点,所以处理答案的过程放在前序位置是最好的。

解题代码

 //用一个哈希表保存,每个结点的父节点,由于此题每个元素不重复,可以使用元素来映射父节点
 //实际上建立哈希表的作用就是为了能够逆向遍历
class Solution {
public:
    vector<int> distanceK(TreeNode* root, TreeNode* target, int k) {
        if(k==0)return vector<int>{target->val};
        parent[root->val] = nullptr;
        dis = k;
        solve(root);
        dfs(target,nullptr,0);
        return res;
    }
private:
    unordered_map<int,TreeNode*>parent;
    vector<int>res;
    int dis;
    //建立哈希表
    void solve(TreeNode* root){
        if(root->left){
            parent[root->left->val] = root;
            solve(root->left);
        }
        if(root->right){
            parent[root->right->val] = root;
            solve(root->right);
        }
    }
    //dfs搜索与target距离为k的结点进行存储,注意通过哈希表进行向上遍历
    void dfs(TreeNode* root,TreeNode* from,int k){
        if(!root)return;
        if(k==dis){
            res.emplace_back(root->val);
            return;
        }
        //防止出现已经到达了上面却还要向下遍历的情况,所以建立的from参数进行判断
        if(root->left!=from){
            dfs(root->left,root,k+1);
        }
        if(root->right!=from){
            dfs(root->right,root,k+1);
        }//判断from是否为其父节点,如果不是,则说明它是从下面来的,所以应该向上面走
        if(parent[root->val]!=from){
            dfs(parent[root->val],root,k+1);
        }
    }
};

题目二:在链表遍历中的运用

深拷贝:复制带随机指针的链表

题目解析

看到链表深拷贝,我们很快想到能直接通过递归new出所有内存空间,可就是random指针无法方便的进行赋值。如何解决这个问题呢?

  • 答案又是哈希表。

没错在链式遍历这一块哈希表是有天然优势的。

我们建立哈希表存储新创建的空间和之前的空间地址的一一映射关系,通过这个关系,我们只需要遍历原链表的 random 指针的值便可以映射到新的空间地址值,接下来怎么做大家就应该都清楚了。

解题代码

class Solution {
public:
    Node* copyRandomList(Node* head) {
        //创建深拷贝,并且构建一一对应的映射关系(方便查找random指针)
        Node * t = head;
        while(t){
            check[t] = new Node(t->val);
            t = t->next;
        }
        //用一个结果指针进行连接
        Node* res = nullptr;
        Node* tt = head;
        while(tt){
            res = check[tt];
            //连next指针
            res->next = check[tt->next];
            //连random指针
            res->random = check[tt->random];
            tt = tt->next;
        }
        return check[head];
    }
private:
    unordered_map<Node*,Node*>check;
};

以上是关于哈希表在遍历链式结构中的运用--以链表和二叉树的遍历为例的主要内容,如果未能解决你的问题,请参考以下文章

C语言数据结构树和二叉树的问题

C数据结构

C数据结构

C数据结构

数据结构学习笔记——广义表树和二叉树的基本知识

数据结构学习笔记——广义表以及树和二叉树的基本知识