二叉树的序列化与反序列化

来源:互联网 发布:决对争锋网络剧百度云 编辑:程序博客网 时间:2024/04/29 00:09

前序+中序 –> 二叉树

Construct Binary Tree from Preorder and Inorder Traversal

# Definition for a binary tree TreeNode.# class TreeNode(object):#     def __init__(self, x):#         self.val = x#         self.left = None#         self.right = Noneclass Solution(object):    def buildTree(self, preorder, inorder):        """        :type preorder: List[int]        :type inorder: List[int]        :rtype: TreeNode        """        return self.getRoot(preorder, inorder)    def getRoot(self, preorder, inorder):        """假定前序和中序序列都是正确的"""        if len(preorder)==0:            return None        # 这是一个临时节点, pre.next指向root        pre = TreeNode(None)        self.f(pre, preorder, inorder, 0, 0, len(preorder), True)        return pre.left    def f(self,parent,pre,ino,i,k,l,isleft):        """        parent: 当前子树的父节点        pre: 整棵树的前序遍历序列        ino: 整棵树的中序遍历序列        i: 当前子树的前序序列在a中的起始位置        k: 当前子树的中序序列在b中的起始位置        l: 当前子树的节点数目        isleft: 标志当前子树是父节点的左子树还是右子树        """        current = TreeNode(pre[i])        if isleft==True:            parent.left = current        else:            parent.right = current        # 已到达叶子节点        if l==1:            return        # 当前子树的左子树的节点数目        num = ino.index(pre[i])-k        # 当前子树的左子树非空        if num!=0:            self.f(current,pre,ino,i+1,k,num,True)        # 当前子树的右子树的节点数目不为0, 即非空        if l-num-1!=0:            self.f(current,pre,ino,i+num+1,k+num+1,l-num-1,False)

注意到num = ino.index(pre[i])-k可以进行优化,提前生成中序序列的元素和索引号的map,可提高查询速度,在getRoot中添加下面的代码:

inomap = {}for i in range(len(inorder)):    inomap[inorder[i]] = i

将调用f时,用inomap替换ino,然后将num = ino.index(pre[i])-k改为num = inomap[pre[i]]-k

现在只有4.42%的提交结果的执行时间比这个少。

中序+后序 –> 二叉树

Construct Binary Tree from Inorder and Postorder Traversal
和上面类似,稍稍改动即可:

# Definition for a binary tree node.# class TreeNode(object):#     def __init__(self, x):#         self.val = x#         self.left = None#         self.right = Noneclass Solution(object):    def buildTree(self, inorder, postorder):        """        :type inorder: List[int]        :type postorder: List[int]        :rtype: TreeNode        """        return self.getRoot(postorder,inorder)    def getRoot(self, postorder, inorder):        if len(postorder)==0:            return None        pre = TreeNode(None)        self.f(pre, postorder, inorder, 0, 0, len(postorder), True)        return pre.left    def f(self,parent,post,ino,i,k,l,isleft):        current = TreeNode(post[i+l-1])        if isleft==True:            parent.left = current        else:            parent.right = current        if l==1:            return        num = ino.index(post[i+l-1])-k        if num!=0:            self.f(current,post,ino,i,k,num,True)        if l-num-1!=0:            self.f(current,post,ino,i+num,k+num+1,l-num-1,False)

二叉树的反序列化

leetcode上二叉树的序列化方法:

OJ's 二叉树序列化
注意,结尾的若干个#直接省略掉。

我完成了反序列化的过程,不过没经过足够多的用例测试:

class node:    def __init__(self, data=None):        self.val = data        self.left = None        self.right = None'''二叉树的某行有n个元素(不包括-1), 下一行一定有2n个元素(包括-1)这个函数用来处理每一行的元素, 如果序列结尾有省略掉的-1, 会触发IndexError, 直接忽略即可'''def layer(q, begin, prelist):    # q序列    # begin当前段的开始位置    # prelist上一段的节点列表    # curlist是当前段的节点列表    curlist = []    try:        # 依次遍历prelist中每个节点        for i in range(len(prelist)):            # i节点的左孩子节点            if q[begin+2*i]>0:                t = node(q[begin+2*i])                prelist[i].left = t                curlist.append(t)            # i节点的右孩子节点            if q[begin+2*i+1]>0:                t = node(q[begin+2*i+1])                prelist[i].right = t                curlist.append(t)    except IndexError:        pass    return curlist# 输入一个二叉树序列, 构建一个二叉树, 返回根节点def buildBinaryTree(q):    if len(q)==0:        return None    root = node(q[0])    lists = [root]    begin = 1    while len(lists)>0:        next = begin+2*len(lists)        lists = layer(q, begin, lists)        begin = next    return root

二叉树的序列化

与上节刚好相反,代码也有些类似。

class node:    def __init__(self, data=None):        self.val = data        self.left = None        self.right = None"""prelist上一层的节点列表curlist这一层的节点列表"""def once(result, prelist):    curlist = []    for i in prelist:        if i.left!=None:            curlist.append(i.left)            result.append(i.left.val)        else:            result.append(-1)        if i.right!=None:            curlist.append(i.right)            result.append(i.right.val)        else:            result.append(-1)    return curlist# 并没有删去结尾的若干-1def serialize(root):    result = [root.val]    lists = [root]    while len(lists)>0:        lists = once(result,lists)    return result

前序遍历

Binary Tree Preorder Traversal
上面的序列化和反序列化实际上是BFS(Breadth-First-Search),下面是用栈实现二叉树的前序遍历,这是个DFS(Depth-First-Search):

/** * Definition for a binary tree node. * struct TreeNode { *     int val; *     TreeNode *left; *     TreeNode *right; *     TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */class Solution {public:    vector<int> preorderTraversal(TreeNode* root) {        vector<int> result;        if(!root) return result;        stack<TreeNode*> valstk;        valstk.push(root);        while(!valstk.empty())        {            TreeNode *p = valstk.top();            valstk.pop();            result.push_back(p->val);            if(p->right)                valstk.push(p->right);            if(p->left)                valstk.push(p->left);        }        return result;    }};

非递归的后序遍历

Binary Tree Postorder Traversal

vector<int> postorderTraversal(TreeNode* root) {    vector<int> result;    if(!root) return result;    stack<TreeNode*> valstk;    valstk.push(root);    TreeNode *pre = root;    while(!valstk.empty())    {        TreeNode *p = valstk.top();        if(p->left==NULL && p->right==NULL || p->left==pre || p->right==pre)        {            valstk.pop();            result.push_back(p->val);            pre = p;        }        else        {            if(p->right) valstk.push(p->right);            if(p->left) valstk.push(p->left);        }    }    return result;}

参考

0 0
原创粉丝点击