题目1503:二叉搜索树与双向链表

题目描述:

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

输入:

输入可能包含多个测试样例。
对于每个测试案例,输入的第一行为一个数n(0<n<1000),代表测试样例的个数。
接下来的n行,每行为一个二叉搜索树的先序遍历序列,其中左右子树若为空则用0代替。

输出:

对应每个测试案例,
输出将二叉搜索树转换成排序的双向链表后,从链表头至链表尾的遍历结果。

样例输入:
1
2 1 0 0 3 0 0
样例输出:

1 2 3

分析:

当读入一个数字不为0时,那么接下来读入的一个数字是以当前读入数字为根节点的左孩子,也就是说,接下来读入的数字在双向链表中是当前读入数字的前驱;当读入一个数字为0时,那么接下来读入的数字在双向链表中是当前读入数字的后继的后继。当理解了这之后,可以依次读入数字,并在一个双向链表上插入新节点,当前节点的数字非零时,即在当前节点之前插入一个新节点作为当前节点的先驱;否则,则在当前节点的后继之后插入一个新节点作为后继的后继。其中关于双向链表的插入过程,需要修改前驱的next和后继的prev指针以及给插入节点的next,prev赋值。

代码如下:

// 1503new.cpp : 定义控制台应用程序的入口点。

//
#include "stdafx.h"
#include<stdio.h>
struct Node{
int e;
Node* next,*prev;
Node(int x=0):e(x),next(NULL),prev(NULL){}
};
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=0;i<n;++i)
{
Node*H=new Node();
Node* p=H;
while(p!=NULL)
{
int tmp;
scanf("%d",&tmp);
p->e=tmp;
if(tmp==0) //接下来读入的数字是当前读入数字的后继的后继,当后继为空时,其实已经不需要插入了,因为读入已经结束
{
if(p->next!=NULL)
{
p=p->next; //p是当前读入的后继,新节点的前驱
Node*q=p->next; //q是当前读入的后继的后继,新节点的后继
p->next=new Node();//插入的新节点
p->next->next=q;
p->next->prev=p;
if(q!=NULL)
{
q->prev=p->next;
}
}
p=p->next;
}
else     //接下来的读入是当前读入的前驱
{
Node *q=p->prev;//p是当前节点,也是新节点的后继,q是当前节点的前驱也是新节点的前驱
p->prev=new Node();//新节点
p->prev->next=p;
p->prev->prev=q;
if(q!=NULL)
{
q->next=p->prev;
}
p=p->prev;
}
}
while(H->prev!=NULL)//寻找头节点
{
H=H->prev;
}
//bool flag=true;
while(H!=NULL)
{
if(H->e!=0)
{
/*if(flag) //让人无语的是,题目居然一点都没有提示说每一个输出数字后面都右一个空格,所以这段代码注释掉了
printf(" ");
flag=true;*/
printf("%d ",H->e);
}
p=H;
H=H->next;
delete p;//释放分配的空间
}
printf("\n");
}
}
return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值