微软面试100题系列-第1题

本文介绍如何将二分查找树转换成排序的双向链表,通过递归方式调整树节点指针,实现不新建节点的目标。文章提供详细步骤及示例代码。
注:微软面试100题系列中的题都是 v_JULY_vhttp://blog.csdn.net/v_JULY_v)收集的面试题,具体PDF下载地址为: http://download.csdn.net/detail/v_july_v/4583815

                写文的目的是锻炼自己,欢迎各位大牛提出建议,批评指正~

第一题:把二分查找树转变成排序的双向链表

输入一棵二分查找树,将该二分查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只调整指针的指向。如:
                                                 

                                                        10

                                                      /      \

                                                    6       14

                                                  /   \       /   \

                                                4    8  12   16
 
转换成双向链表4=6=8=10=12=14=16 。

我们定义的二分查找树结点的数据结构如下:
struct BSTreeNode
{
  int m_nValue; // value of node
  BSTreeNode *m_pLeft; // left child of node
  BSTreeNode *m_pRight; // right child of node
};

 

我的解题思路如下:

      本题中不能建立新的结点,只能改变指针的指向。先观察根结点,根据二叉查找树的特点,可以发现根结点的左指针应该指向左子树双向链表的尾部,而根结点的右指针

应该指向右子树双向链表的头部。因此该问题可以递归为求解左、右孩子的双向链表。求解完左、右孩子的双向链表后,再接上根结点,即可完成对双向链表的求解。

     根据上述思路,先来看一下代码结构,之后会有例子讲解。

      编写如下的递归函数:

      void ConvertRecursive(BSTNode* &subHead, BSTNode* &subTail, BSTNode* subRoot)

      然后在函数中求解左、右孩子的双向链表:

      BSTNode *leftTail = NULL, *rightHead = NULL;

      ConvertRecursive(subHead,leftTail,subRoot->pLeft);  //求解左子的链表

      ConvertRecursive(rightHead,subTail,subRoot->pRight);  //求解右子的链表

      。。。。。。 //将左子链表、根、右子链表连接起来

      这个递归初看可能有点不清晰,我们可以先看一下求解左子链表的语句:

      ConvertRecursive(subHead,leftTail,subRoot->pLeft);   

       这个subHead可看成是当前链表的头,在递归结束后,最上一层的subHead将是整个双向链表的头。而leftTail是我们想要的左孩子双向链表的尾部。

       ConvertRecursive(rightHead,subTail,subRoot->pRight); 

       rightHead是我们想要的右孩子双向链表的头部,而subTail可看成是当前链表的尾,在递归结束后,最上一层的subTail将是整个双向链表的尾。

       现在看一下左子链表、根与右子链表连接的操作:如果左子没有双向链表,那么根结点就成为当前链表的头;如果有,根结点就连接上左子链表的尾部。

       同理,如果右子没有链表,那么根结点就成为当前链表的尾;如果有,则根结点与右子链表的头部相连接。

//连接左子链表与根
  if (leftTail == NULL)  //左子没有双向链表
  {
       subHead = subRoot;
  }
  else
  {
      leftTail->pRight = subRoot;
      subRoot->pLeft = leftTail;
  }

  //连接右子链表与根
  if (rightHead == NULL) //右子没有双向链表
  {
      subTail = subRoot;
  }
  else
  {
      subRoot->pRight = rightHead;
      rightHead->pLeft = subRoot;
  }

         以子树        6                   为例,

                          /        \

                       4           8

         递归到4时,因为4是叶子结点,其左、右子树链表为空,则有subHead -> 4, subTail -> 4。同理8也是这种情况。

         返回到6的调用,因为6调用4的递归中,形参subTail实际上是实参leftTail的引用,因此6的左子链表leftTail->4不为空,按照之前的思路,我们可以将结点6与左子链表连

接起来,就有了链表4=6;同理,在6调用8的递归中,形参subHead实际上是实参rightHead的引用,因此6的右子链表rightHead->8也不为空,将6与右子链表连接起来,我们

有了双向链表4=6=8,而此时当前链表的subHead->4,subTail->8。

由此,可以看出整个递归过程中,leftTail和rightHead起到了连接整个链表中间结点的作用,而subHead和subTail则保存了目前递归层次中的最小和最大值。

         完整的代码如下,因为自己有一个BST树结点的模板类,所以直接拿来用了,BSTNode<int>和题目中的BSTreeNode的结构是一样的。

//written by zero

#include "BST.h"
#include <iostream>

using namespace std;

void ConvertRecursive(BSTNode<int>* &subHead, BSTNode<int>* &subTail, BSTNode<int>* subRoot)
{
	 BSTNode<int> *leftTail = NULL, *rightHead = NULL;

	 if (subRoot == NULL)
	 {
		 subHead = NULL;
		 subTail = NULL;
		 return;
	 }

	 ConvertRecursive(subHead,leftTail,subRoot->pLeft);  //求解左子的链表
	 ConvertRecursive(rightHead,subTail,subRoot->pRight);  //求解右子的链表

	 //将左子链表,根,右子链表接在一起

	 //连接左子链表与根
	 if (leftTail == NULL)  //左子没有双向链表
	 {
		 subHead = subRoot;
	 }
	 else
	 {
		 leftTail->pRight = subRoot;
		 subRoot->pLeft = leftTail;
	 }

	 //连接右子链表与根
	 if (rightHead == NULL) //右子没有双向链表
	 {
		 subTail = subRoot;
	 }
	 else
	 {
		 subRoot->pRight = rightHead;
		 rightHead->pLeft = subRoot;
	 }

}

int main()
{
	//建立二叉查找树
	BSTree<int> tree;
	tree.Insert(10);
	tree.Insert(6);
	tree.Insert(14);
	tree.Insert(4);
	tree.Insert(8);
	tree.Insert(12);
	tree.Insert(16);

	/*tree.TravelRecursive(&BSTree<int>::PosOderRecursive,&BSTree<int>::process);
	cout << endl;
	tree.TravelRecursive(&BSTree<int>::PosOderNonRecursive,&BSTree<int>::process);
	cout << endl;*/

	//转换成双向链表
	BSTNode<int> *head = NULL, *tail = NULL, *pNode;
	ConvertRecursive(head,tail,tree.root);

	//验证正向遍历双向链表
	cout << "正向遍历链表:";
	pNode = head;
	while(pNode)
	{
		cout << pNode->value << " ";
		pNode = pNode->pRight;
	}
	cout << endl;

	//验证逆向遍历双向链表
	cout << "逆向遍历链表:";
	pNode = tail;
	while(pNode)
	{
		cout << pNode->value << " ";
		pNode = pNode->pLeft;
	}
	cout << endl;
}


运行结果如下:

内容概要:本文主要介绍了一个基于Matlab实现的无人机空中通信仿真项目,旨在通过数值仿真手段研究无人机在空中作为通信节点时的通信性能、信号传播特性和网络拓扑行为。该仿真涵盖了无人机飞行轨迹建模、无线信道建模(如路径损耗、多普勒效应、阴影衰落等)、通信链路建立与中断判断、信号干扰分析以及网络性能评估(如吞吐量、延迟、连接可靠性等)。项目可能结合优化算法或智能控制策略,用于优化无人机位置部署或动态路径规划,以提升通信服务质量。整个仿真系统为研究人员提供了一套完整的工具链,用于验证新型无人机通信协议、协作机制和网络架构的有效性。; 适合人群:具备一定Matlab编程基础和通信原理基础知识,从事无人机、无线通信、网络优化等相关领域研究的研发人员和高校研究生。; 使用场景及目标:① 评估无人机作为空中基站或中继节点的通信覆盖能力和网络性能;② 设计和优化无人机集群的通信拓扑与协同策略;③ 验证新型无线资源分配、移动性管理和抗干扰算法在动态空地网络中的有效性。; 阅读建议:使用者应结合Matlab代码深入理解仿真模型的构建逻辑,重点关注通信信道模块和无人机运动学模型的耦合关系,并可根据实际研究需求,对仿真参数(如环境噪声、飞行速度、天线增益)进行调整,以开展针对性的对比实验和性能分析。
内容概要:本文围绕微电网中光伏发电系统经逆变器带负载的完整仿真模型展开研究,利用Simulink平台构建了从光伏阵列建模、DC-AC逆变器控制(包括PWM调制与电压电流双闭环控制)、并网策略到负载响应的全过程仿真系统。重点分析了系统在不同工况下的动态响应特性与电能质量表现,并对并网控制策略、最大功率点跟踪(MPPT)技术及系统稳定性进行了深入探讨和验证。该模型不仅可用于教学演示微电网的基本架构与运行机制,更为科研提供了可靠的仿真平台,支持对新型控制算法与系统优化方案的有效验证与评估。; 适合人群:具备一定电力电子技术、自动控制理论基础及Simulink/MATLAB操作经验的电气工程、自动化等相关专业的本科生、研究生及科研人员。; 使用场景及目标:①用于高校课程教学中微电网系统结构与运行原理的直观演示;②为科研工作者提供光伏发电并网系统的仿真验证平台,支持开展逆变器控制算法(如双闭环控制、MPPT)、系统稳定性分析及电能质量管理等关键技术的研究与优化。; 阅读建议:建议学习者结合Simulink仿真环境动手搭建模型,重点关注各功能模块间的信号传递关系与关键参数设置,并通过调整光照强度、温度、负载大小等外部条件,观察系统动态响应过程,从而深化对微电网运行特性的理解与掌握。
内容概要:本文围绕“多变量输入超前多步预测”的光伏功率预测问,提出了一种基于CNN-BiLSTM混合深度学习模型的研究方法,并提供了完整的Matlab代码实现。该模型首先利用卷积神经网络(CNN)提取输入气象数据(如光照强度、温度、湿度等)中的局部关键特征,捕捉变量间的空间相关性;随后,通过双向长短期记忆网络(BiLSTM)充分挖掘时间序列数据中的长期依赖关系,既能利用历史信息,也能结合未来时刻的上下文信息,从而实现对未来多个时间步长的光伏功率进行高精度预测。研究重点在于处理多变量输入和满足超前多步预测的实际工程需求,有效提升了预测的准确性与鲁棒性。; 适合人群:具备一定机器学习和深度学习理论基础,熟悉Matlab编程,从事新能源发电预测、电力系统调度、时间序列分析等相关领域的研究人员和工程技术人员。; 使用场景及目标:① 解决光伏出力受多重气象因素影响的复杂非线性预测问;② 实现未来一段时间(如未来24小时)的功率超前多步预测,为电网调度、储能管理和电力市场交易提供决策依据;③ 学习和复现先进的CNN与BiLSTM融合模型在能源预测领域的具体应用。; 阅读建议:使用者应重点关注模型的网络结构设计、多变量数据预处理流程以及多步预测的实现策略。建议结合提供的Matlab代码,自行准备或替换实际的光伏电站运行数据与气象数据,通过调整模型超参数(如卷积核大小、LSTM隐藏层维度、训练周期等)进行实验,以深入理解模型性能并将其应用于具体的科研或工程项目中。
内容概要:本文介绍了一种基于Simulink的光伏储能单相逆变器并网仿真模型,系统性地实现了光伏储能系统与电网之间的能量转换与并网控制全过程。该模型涵盖逆变器的PWM调制、并网同步控制、功率调节策略以及储能单元的能量管理机制,能够精确模拟光照强度变化、负载波动及电网扰动等多种实际运行工况下的系统动态响应特性。通过模块化建模方法,模型具备良好的可扩展性与灵活性,便于研究人员对并网电能质量、控制算法性能及系统稳定性进行深入分析与优化设计。; 适合人群:具备电力电子、新能源发电或自动控制等相关专业背景的本科高年级学生、研究生,以及从事光伏并网系统研发的工程技术人员。; 使用场景及目标:①作为教学工具,帮助学生理解光伏并网逆变器的工作原理与控制逻辑;②服务于科研项目,用于并网控制算法(如PI、PR、重复控制等)的设计、仿真验证与性能对比;③辅助完成毕业设计或工程项目中的系统仿真环节;④为实际工程应用提供前期仿真验证与技术预研支持。; 阅读建议:建议使用者在学习前巩固电力电子技术和可再生能源系统的基础理论,按照模型结构逐步搭建与调试;可利用文中提供的仿真框图和参数设置进行复现,并尝试引入不同工况(如光照突变、电网电压波动等)以评估系统的鲁棒性与适应性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值