二叉树的镜像 (剑指offer)!!!(两个有序链表的合并,链表的逆置)

面试题19:二叉树的镜像(来自《剑指Offer》)

题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像。

二叉树结点的定义如下:

  1. struct BinaryTreeNode  
  2. {  
  3.     int data;  
  4.     BinaryTreeNode *Left;  
  5.     BinaryTreeNode *Right;  
  6. };  

通过画图,可知二叉树的镜像如下图所示:


根据画图可得到这样的思路:先序遍历树的每个结点,若遍历到的结点有子结点,则交换它的两个子结点。

有两种实现方法:

1.递归实现

  1. void MirroRecursively(BinaryTreeNode *pNode)  
  2. {  
  3.     if(NULL == pNode)  
  4.         return;  
  5.     if(NULL == pNode->Left && NULL == pNode->Right)  
  6.         return;  
  7.       
  8.     BinaryTreeNode *pTemp = pNode->Left;  
  9.     pNode->Left = pNode->Right;  
  10.     pNode->Right = pTemp;  
  11.       
  12.     if(pNode->Left)  
  13.         MirroRecursively(pNode->Left);  
  14.     if(pNode->Right)  
  15.         MirroRecursively(pNode->Right);  
  16. }  

2.非递归实现,即使用循环实

void MirrorNonRecurively(BinaryTreeNode *pNode)  
{  
    if(NULL == pNode)  
        return;  
  
    stack<BinaryTreeNode *> stackTreeNode;  
    stackTreeNode.push(pNode);  
  
    while(stackTreeNode.size())  
    {  
        BinaryTreeNode *pNode = stackTreeNode.top();  
        stackTreeNode.pop();  
  
        if(NULL != pNode->Left || NULL != pNode->Right)  
        {  
            BinaryTreeNode *pTemp = pNode->Left;  
            pNode->Left = pNode->Right;  
            pNode->Right = pTemp;  
        }  
          
        if(NULL != pNode->Left)  
            stackTreeNode.push(pNode->Left);  
  
        if(NULL != pNode->Right)  
            stackTreeNode.push(pNode->Right);  
    }  
} 






链表的逆置问题:

利用链表的头插法和尾插法

1,我们不应该使得链表断裂,也就是说:无论什嘛时候,我们都必须能访问到数据

void Reverse(LinkList H)
{
        LNode *p, *q;
        p = H->next;
        H->next = NULL;
        while(p)
        {
                q = p;
                p = p->next;
                q->next = H->next;
                H->next = q;
        }
}



合并两个排序的链表

1,容易犯的两种错误:

  1,在写代码之前没有对合并的过程想清楚,最终合并出来的链表要么中间断开了要么并没有做到

    递增排序;

  2,代码在鲁棒性方面存在问题,程序一旦有特殊的输入(如:空链表)就会崩溃

    1,第一个链表是空链表,也就是头节点是一个空指针,那么它和第二个链表合并,显然合并

      的结果就是第二个链表;同样的,当输入的第二个链表的头节点是空指针的时候,我们把

      它和第一个链表合并得到的结果就是第一个链表;如果两个链表都是空的,那么合并的结

      果就是一个空链表。。。。。。。


    Node *ListMerge1(Node *head1,Node *head2)//采用递归的方法实现  
    {  
        if(head1==NULL)  
            return head2;  
        if(head2==NULL)  
            return head1;  
        Node *head=NULL;  
        if(head1->value < head2->value)  
        {  
            head=head1;  
            head->next=ListMerge1(head1->next,head2);  
        }  
        else  
        {  
            head=head2;  
            head->next=ListMerge1(head1,head2->next);  
        }  
        return head;  
    }  



算法的非递归实现如下:

Node *ListMerge(Node *head1,Node *head2)
{
	if(!head1) return head2;
	if(!head2) return head1;
	Node *head=NULL;//合并后的头指针
	Node *p1=head1;//p1用于扫描链表1
	Node *p2=head2;//p2用于扫描链表2
	if(head1->value<head2->value)
	{
		head=head1;
		p1=head1->next;
	}
	else
	{
		head=head2;
		p2=head2->next;
	}
	Node *p=head;//p永远指向最新合并的结点
	while(p1 && p2)//如果循环停止,则p1或p2至少有一个为NULL
	{
		if(p1->value<p2->value)
		{
			p->next=p1;
			p1=p1->next;
		}
		else
		{
			p->next=p2;
			p2=p2->next;
		}
		p=p->next;
	}
	if(p1)//如果链1还没走完
	{
		p->next=p1;
	}
	else if(p2)//如果链2还没走完
	{
		p->next=p2;
	}
	return head;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值