二叉排序树转化成双向链表

2023-11-16

题目描述:

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

输入:

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

输出:

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

样例输入:
1
2 1 0 0 3 0 0
样例输出:
1 2 3
思路:
1.二叉排序树的特点就是一个结点的左子树比它小,右子树比它大,所以可以根据中序遍历得到一棵排序的序列。
2.若不能创建新结点,那么我们只能去修改原始二叉树的指针。这里我们让指向左子树的指针变为链表中指向前一个结点的指针,而指向右子树的指针变为链表中指向后一个结点的指针。
3.结合上面两点,很容易写出一个递归的算法。如下:

代码:

/*
二叉排序树转双向链表
by Rowandjj
2014/8/6
*/
#include<stdio.h>
#include<stdlib.h>
typedef struct _BNODE_
{
	int data;
	struct _BNODE_ *left;
	struct _BNODE_ *right;
}BNode,*pNode,*pTree;
//---------------------------------------
//其实是一个中序遍历的过程,因为中序遍历二叉排序树可以得到有序序列
void ConvertNode(pTree pRoot,pNode *pTail)
{ 
	if(pRoot == NULL)
	{
		return;
	}
	//左
	pNode pCur = pRoot;
	if(pCur->left != NULL)
	{
		ConvertNode(pCur->left,pTail);
	}
	//根 
	//left指针指向前一个,right指针指向后一个
	pCur->left = *pTail;
	if(*pTail != NULL)
	{
		(*pTail)->right = pCur;
	}
	*pTail = pCur;
	//右
	if(pCur->right != NULL)
	{
		ConvertNode(pCur->right,pTail);
	}
	
}
//将二叉排序树转化为双向链表,返回双向链表头指针
pNode Convert(pTree pRoot)
{
	if(pRoot == NULL)
	{
		return NULL;
	}
	pNode pTail = NULL;
	ConvertNode(pRoot,&pTail);
	pNode pHead = pTail;
	//根据双向链表的尾找到其头指针
	while(pHead != NULL && pHead->left != NULL)
	{
		pHead = pHead->left;
	}
	//返回双向链表头指针
	return pHead;
}
//遍历双向链表
void DisplayLinkedList(pNode pHead)
{
	if(pHead == NULL)
	{
		return;
	}
	pNode pTemp = pHead;
	while(pTemp != NULL)
	{
		printf("%d ",pTemp->data);
		pTemp = pTemp->right;
	}
	printf("\n");
}
//销毁双向链表
void DestroyList(pNode *pHead)
{
	if(*pHead == NULL)
	{
		return;
	}
	pNode p = *pHead,q;
	while(p != NULL)
	{
		q = p->right;
		free(p);
		p = q;
	}
	pHead = NULL;
}
//---------------------------------------
//先序构建二叉树
void CreateTree(pTree *pRoot)
{
	int data;
	scanf("%d",&data);
	if(data == 0)
	{
		return;
	}
	*pRoot = (pNode)malloc(sizeof(BNode));
	if(*pRoot == NULL)
	{
		exit(-1);
	}
	(*pRoot)->data = data;
	(*pRoot)->left = NULL;
	(*pRoot)->right = NULL;
	CreateTree(&(*pRoot)->left);
	CreateTree(&(*pRoot)->right);
}
//先序遍历排序树
void DisplayTree(pTree pRoot)
{
	if(pRoot == NULL)
	{
		return;
	}
	printf("%d ",pRoot->data);
	DisplayTree(pRoot->left);
	DisplayTree(pRoot->right);
}
void DestroyTree(pTree *pRoot)
{
	if(*pRoot == NULL)
	{
		return;
	}
	if((*pRoot)->left != NULL)
	{
		DestroyTree(&(*pRoot)->left);
	}
	if((*pRoot)->right != NULL)
	{
		DestroyTree(&(*pRoot)->right);
	}
	free(*pRoot);
	*pRoot = NULL;
}
int main()
{
	int n;
	while(scanf("%d",&n) != EOF)
	{
		if(n <= 0)
		{
			continue;
		}
		for(int i = 0; i < n; i++)
		{
			pTree pRoot = NULL;
			CreateTree(&pRoot);
			pNode pHead = Convert(pRoot);
			if(pHead != NULL)
			{
				DisplayLinkedList(pHead);
			}
			DestroyList(&pHead);
		}
	}
	return 0;
}

部分函数并没有使用,可以去掉



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二叉排序树转化成双向链表 的相关文章

随机推荐

  • 报错:selenium.common.exceptions.WebDriverException: Messag‘geckodriver‘ execute

    问题原因 使用pip安装selenium 默认安装的是最新版本的selenium selenium 3 x开始 webdriver firefox webdriver py的 init 中 executable path geckodriv
  • Git——Day3(Github Pages搭建个人网站)

    1 个人站点访问 https github用户名 github io 2 搭建步骤 1 创建个人站点 gt 新建仓库 注 仓库名必须是 用户名 github io 2 在仓库下新建index html的文件即可 注意 1 github pa
  • Python报错socket.gaierror: [Errno 11001] getaddrinfo failed

    1 报错 from scapy all import sr IP ICMP target 192 168 142 129 pkt IP dst target ICMP ans unans sr pkt timeout 1 for s r i
  • GitHub Desktop客户端下载安装,以及上传到服务端

    下载安装地址 https desktop github com 使用教程 https blog csdn net qqw666666 article details 125652869 操作流程 就是不同应用端的交互 做好相关验证即可
  • 应用中间件二、Tomcat单机多实例部署

    Tomcat 常见的几种部署场景 通常 我们在同一台服务器上对 Tomcat 部署需求可以分为以下几种 单实例单应用 单实例多应用 多实例单应用 多实例多应用 实例的概念可以理解为上面说的一个 Tomcat 目录 单实例单应用 比较常用的一
  • Python3.x opencv操作中文文件

    我用的是python3 5 本身用file打开中文文件是没有问题的 但是用opencv就不行 网上看到很多解决版本 可能都是针对python2 x的 没有效果 后来在知乎上看到一个解决方法 测试有效 引用在这里 冯卡门 由于python3字
  • Redis底层数据结构.md

    1 Redis 概述 Redis 数据库里面的每个键值对 key value 都是由对象 object 组成的 数据库键总是一个字符串对象 string object 数据库的值则可以是字符串对象 列表对象 list 哈希对象 hash 集
  • Jmeter对图片验证码的处理

    jmeter对图片验证码的处理 在web端的登录接口经常会有图片验证码的输入 而且每次登录时图片验证码都是随机的 当通过jmeter做接口登录的时候要对图片验证码进行识别出图片中的字段 然后再登录接口中使用 通过jmeter对图片验证码的识
  • ctfshow—萌新—web1

    0x00 前言 CTF 加解密合集 CTF Web合集 0x01 题目 0x02 Write Up 解法1 标准的数字型注入 查列名 http cc3ecc3f 8c42 4624 979e 277a51ea85d2 challenge c
  • 【面经】外企德科-华为精英研发项目-笔试编程题

    微信搜索 编程笔记本 获取更多干货 微信搜索 编程笔记本 获取更多干货 点击上方蓝字关注我 我们一起学编程 欢迎小伙伴们分享 转载 私信 赞赏 今天来看一道 外企德科 华为精英研发项目 的一道笔试编程题 求满足条件的最长字串的长度 题目描述
  • 一次 Young GC 的优化实践

    这个 GC 案例比较有意思 排查问题有点像侦探断案 先分析各种可能性 再按照获得的一个个证据 去排除各种可能性 然后定位原因 最终解决问题 问题 某同学在微信上问我 有没有办法排查 YoungGC 效率低的问题 听到这话 我也是不知从何说起
  • Linux网络编程:Socket套接字编程(Server服务器 Client客户端)

    文章目录 一 定义和流程分析 1 定义 2 流程分析 3 网络字节序 二 相关函数 IP地址转换函数inet pton inet ntop 本地字节序 网络字节序 socket函数 创建一个套接字 bind函数 给socket绑定一个服务器
  • 引领AI数据标注行业,景联文科技提供高质量图像和文本标注服务

    近年来 我国的数据要素市场呈现出高速增长的趋势 根据国家工信安全中心的统计数据 截至2022年 我国数据要素市场规模已达到815亿元 同比增长49 51 数据要素作为数字经济时代的关键要素 是构建新发展格局的重要支撑 其重要性日益凸显 党中
  • Android开发学习之路-基本事件的使用

    1 事件的响应方法 setOnClickListener view OnClickListener l setOnFocusChangeListener view OnFocusChangeListener l setOnLongClick
  • [从零开始学习FPGA编程-37]:进阶篇 - 基本时序电路-有限状态机实现(Verilog)

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 目录 第1章 状态机概述 1 1 UML描述状态机 1 2 数字电路描述状态机
  • VScode的代码截图插件CodeSnap

    CodeSnap 在 VS Code 中为您的代码截取漂亮的屏幕截图 插件名 CodeSnap 官方地址 CodeSnap Visual Studio Marketplace 特征 快速保存代码的屏幕截图 将屏幕截图复制到剪贴板 显示行号
  • user-select不可被用户选中

    目录 背景 字段属性 注意 案例 背景 项目中有这种奇葩需求 就是特定字段不让用户复制 不可被选中状态 这种应用场景最多的就是考试系统啥的吧 不让考生复制题目搜题 真恶心 字段属性 注意 浏览器实现之间的区别之一是继承 案例
  • 我用Python做副业,月赚1W+:千万别让死工资拖垮了自己。。

    被压垮的打工人 你还好吗 房贷车贷 上老下小 日常开销节省不了 但你的收入有多少 所以不敢生病 甚至不敢回家 就为了每个月那么点死工资 还得天天加班 然而忙忙忙 却变成了 穷忙族 成为了职场废人 其实很多人都想改变现状 想学点什么的 但就是
  • Proxy error: Could not proxy request错误解决

    vue 项目 错误原因 跨域 解决办法 package json文件中的scripts调试添加 start node index js server nodemon index js ignore client 这篇文章解释的很清楚http
  • 二叉排序树转化成双向链表

    题目描述 输入一棵二叉搜索树 将该二叉搜索树转换成一个排序的双向链表 要求不能创建任何新的结点 只能调整树中结点指针的指向 输入 输入可能包含多个测试样例 对于每个测试案例 输入的第一行为一个数n 0