输入一颗二元查找树,将该树转换为它的镜像

微软面试题,难度系数中下,题目描述如下:

题目:输入一颗二元查找树,将该树转换为它的镜像, 
即在转换后的二元查找树中,左子树的结点都大于右子树的结点。 
用递归和循环两种方法完成树的镜像转换。 
例如输入: 
          8 
        /     \ 
      6     10 
     / \      /  \ 
   5   7  9   11 
输出: 

              8 

            /   \ 
         10     6 
         /  \     / \ 
      11  9  7   5 

逻辑分析:

1、之所以判定题目难度中下,原因在于这里要求用递归和非递归分别实现。我们知道,但凡是树的问题,大多递归可轻松解,本题也一样,仔细分析过后,没有多大难度,只是交换每一个节点的左右孩子而已。

我们定义二叉排序树节点:

typedef struct BSTreeNode          //a node in the BST
{
    int m_nValue;                  //Value of node
    struct BSTreeNode *m_pLeft;    //left child of node
    struct BSTreeNode *m_pRight;   //right child of node
}BSTreeNode;

下面给出递归实现:

void ExchangeTree(BSTreeNode* root)
{
    if(root)
    {
        ExchangeTree(root->m_pLeft);
        ExchangeTree(root->m_pRight);
        BSTreeNode* temp = root->m_pLeft;
        root->m_pLeft = root->m_pRight;
        root->m_pRight = temp;
    }
}


2、如果采用循环迭代,那么就非常类似二叉树非递归遍历,这里采用类似先序遍历的方式,借助一个辅助栈来实现,每一次完成交换左右孩子后,将当前的“根”节点入栈,然后向左进行循环交换,当左侧完结时,如果辅助栈中还有元素,那么取出来,将其右孩子作为下一次循环的起始点。当公交车指针p为空,且辅助栈也空时,交换完毕。

非递归实现:

void ExchangeTree(BSTreeNode* root)
{
    Stack S;
    InitialStack(&S);
    BSTreeNode *p = root;
    while(p != NULL || !isEmptyStack(&S))
    {
        if(p != NULL)
        {
            BSTreeNode *temp = p->m_pLeft;
            p->m_pLeft = p->m_pRight;
            p->m_pRight = temp;
            Push(&S, p);
            p = p->m_pLeft;
        }
        else
        {
            BSTreeNode *temp = Pop(&S);
            p = temp->m_pRight;
        }
    }
}

3、下面给出完整的代码实现,内置两种实现方式,匆忙写的,细节上可能仍然存在bug。

#include <stdio.h>

typedef struct BSTreeNode          //a node in the BST
{
    int m_nValue;                  //Value of node
    struct BSTreeNode *m_pLeft;    //left child of node
    struct BSTreeNode *m_pRight;   //right child of node
}BSTreeNode;

/*
void ExchangeTree(BSTreeNode* root)
{
    if(root)
    {
        ExchangeTree(root->m_pLeft);
        ExchangeTree(root->m_pRight);
        BSTreeNode* temp = root->m_pLeft;
        root->m_pLeft = root->m_pRight;
        root->m_pRight = temp;
    }
}
*/
typedef struct Stack
{
    BSTreeNode* elem[100];
    int top;
    int size;
}Stack;

void InitialStack(Stack* S)
{
    S->top = 0;
    S->size = 0;
}

int isEmptyStack(Stack* S)
{
    if(S->size == 0)
        return 1;
    else
        return 0;
}

void Push(Stack *S, BSTreeNode* node)
{
    S->elem[S->top] = node;
    S->top++;
    S->size++;
}

BSTreeNode* Pop(Stack *S)
{
	if(S->size == 0)
		return NULL;
	BSTreeNode* temp = S->elem[S->top-1];
    S->top--;
    S->size--;
    return temp;
}

void ExchangeTree(BSTreeNode* root)
{
    Stack S;
    InitialStack(&S);
    BSTreeNode *p = root;
    while(p != NULL || !isEmptyStack(&S))
    {
        if(p != NULL)
        {
            BSTreeNode *temp = p->m_pLeft;
            p->m_pLeft = p->m_pRight;
            p->m_pRight = temp;
            Push(&S, p);
            p = p->m_pLeft;
        }
        else
        {
            BSTreeNode *temp = Pop(&S);
            p = temp->m_pRight;
        }
    }
}

void DLR(BSTreeNode* root)
{
    if(root == NULL)
        return ;
    printf("%d\n",root->m_nValue);
    DLR(root->m_pLeft);
    DLR(root->m_pRight);
}

int main()
{
    BSTreeNode node[7];

    node[0].m_nValue = 8;
    node[0].m_pLeft = &node[1];
    node[0].m_pRight = &node[2];

    node[1].m_nValue = 6;
    node[1].m_pLeft = &node[3];
    node[1].m_pRight = &node[4];

    node[2].m_nValue = 10;
    node[2].m_pLeft = &node[5];
    node[2].m_pRight = &node[6];

    node[3].m_nValue = 5;
    node[3].m_pLeft = NULL;
    node[3].m_pRight = NULL;

    node[4].m_nValue = 7;
    node[4].m_pLeft = NULL;
    node[4].m_pRight = NULL;

    node[5].m_nValue = 9;
    node[5].m_pLeft = NULL;
    node[5].m_pRight = NULL;

    node[6].m_nValue = 11;
    node[6].m_pLeft = NULL;
    node[6].m_pRight = NULL;

    ExchangeTree(&node[0]);

    DLR(&node[0]);

    return 0;
}

两种方式实现的结果图:

递归:



非递归:


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值