编程之美 - 重建二叉树

来源:互联网 发布:分布式关系型数据库 编辑:程序博客网 时间:2024/05/16 06:18
问题描述: 给出二叉树先序遍历和中序遍历的结果,根据结果重建二叉树。

举例: 例如二叉树


pic_1


先序遍历结果 为 abdcef  中序遍历结果为 dbaecf,现根据结果重构二叉树。

思路: 关键需要找到二叉树每一层的根节点和子树的长度。
例如先序遍历中根节点必然是第一个 abdcef ,  通过中序遍历可以发现 dbaecf a的左侧有两个,右侧有3个,说明左子树侧有两个元素,右子树侧有3个元素。
在先序遍历中,挨着a的元素,和与a相聚 pos_a_in_pre+(pos_a_in_mid+1)的元素便是下一层左右子树根的位置
e f。  再依照这个方法递归,就可以重构出二叉树。

示例程序:

typedef struct _node_st{    char _data;    _node_st* _pleft;    _node_st* _pright;} node_st;node_st* rebuild_pre_in1(char* pPreOrder, char* pMidOrder, int nLen){    node_st* pNewNode = NULL;    int i = 0;    if ((nLen == 0) || (NULL == pPreOrder) || (NULL == pMidOrder))    {        return NULL;    }    pNewNode = new node_st();    pNewNode->_data = pPreOrder[0];    for (i = 0 ;i < nLen; i++)    {        if (pPreOrder[0] == pMidOrder[i])            break;    }    pNewNode->_pleft  = rebuild_pre_in1(pPreOrder+1, pMidOrder, i);    pNewNode->_pright = rebuild_pre_in1(pPreOrder+1+i, pMidOrder+i+1, nLen-i-1);    return pNewNode;}node_st* rebuild_pre_in2(char* pre, char* mid, int start, int length){    node_st *node;    int j = 0;    if ((length <= 0) || ((pre == NULL) || (mid == NULL)))       return NULL;    node = new node_st;    node->_data = pre[start];    node->_pleft = node->_pright = NULL;    if (1 == length)        return node;    for (j = 0; j < length; j++)    {        if (mid[start+j] == node->_data)            break;    }    node->_pleft  = rebuild_pre_in2(pre, mid, start+1, j);    node->_pright = rebuild_pre_in2(pre, mid, start+(j+1), length-j-1);    return node;}void main(){    char pre[] = {'a','b','d','c','e','f'};    char mid[] = {'d','b','a','e','c','f'};    int len = sizeof(pre)/sizeof(pre[0]);    node_st* proot = NULL;    proot = rebuild_pre_in1(pre, mid, 0, len);    proot = rebuild_pre_in2(pre, mid, 0, len);    cin>> len;}

扩展问题
问题描述: 给出二叉树后序遍历和中序遍历的结果,根据结果重建二叉树。

一棵二叉树后序遍历结果 为 dbefca  中序遍历结果为 dbaecf,现根据结果重构二叉树。
与先序遍历相反,后序遍历的结果根节点在最后一个元素。同样可以根据后序找根节点,根据中序找子树中元素个数。
根节点为 a dbefca, dbaecf a的左侧有两个元素,右边有三个元素,这样可以开始找a 的左/右子树的根节点

因为右子树有三个元素, 在后序遍历的结果中从根节点向前跳过三个元素便是左子树的根了,挨着a的便是右子树的根

pic_2


然后从中序遍历中分别计算出左侧搜索的起始点,和右侧搜索的起点,再找到下一层左右子树的元素个数。


pic_3


示例程序:

typedef struct _node_st{    char _data;    _node_st* _pleft;    _node_st* _pright;} node_st;node_st* rebuild_pst_in1(char* pst, char* mid, int start, int length, int search_start){    node_st *node;    int j = 0;    if ((length <= 0) || (start < 0) || ((pst == NULL) || (mid == NULL)))        return NULL;    node = new node_st;    node->_data = pst[start];    node->_pleft = node->_pright = NULL;    if (1 == length)        return node;    for (j = 0; j < length && (start-j)>=0; j++)    {        if (mid[search_start-j] == node->_data)            break;    }    node->_pleft  = rebuild_pst_in1(pst, mid, start-j-1, length-j-1, start-j-1);    node->_pright = rebuild_pst_in1(pst, mid, start-1, j, length-1);  //  search_start : (length-j-1+j)==> length-1    return node;}void main(){    char pre[] = {'a','b','d','c','e','f'};    char mid[] = {'d','b','a','e','c','f'};    char pst[] = {'d','b','e','f','c','a'};    int len = sizeof(pre)/sizeof(pre[0]);    node_st* proot = NULL;    proot = rebuild_pst_in1(pst, mid, len-1, len, len-1);    cin>> len;}





0 0
原创粉丝点击