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

题目描述:

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

输入:

输入可能包含多个测试样例。

对于每个测试案例,输入的第一行为一个数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;
}

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

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

时间: 2024-08-05 01:29:55

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

二元查找树转化成排序的双向链表——要求不创建新的节点

码完第一次编译运行居然就成功了...高兴~ 问题描述: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表.要求不能创建任何新的结点,只调整指针的指向.例如: 10 /    \ 6     14 / \      /  \ 4   8  12  16 转换成双向链表 4=6=8=10=12=14=16 算法: 如果没有"不能创建任何新的结点"的限制,只需进行一次中序遍历,对每个节点的data值构造一个新节点即可. 由于条件限制,现在我们只能用现有的节点,调整他们的指针指向,把

iOS开发之---将时间戳,转化成时间字符串。

1.将一个NSDate,转化成时间字符串. NSDate *date = [NSDate date]; NSDateFormatter *fmt = [[NSDateFormatter alloc] init]; fmt.dateFormat = @"yyyy-MM-dd"; NSString *dateStr = [fmt stringFromDate:date];

将华氏温度转换成摄氏温度或将摄氏温度转化成华氏温度。(需考虑多种不合法的情况尽量转化为合法的)

//华氏温度与摄氏温度转换,编写一个程序,将华氏温度转换成摄氏温度或将摄氏温度转化成华氏温度. //要求程序运行时从控制台读入温度值及单位,并输出另一种温度值及单位,例如:若用户输入27 C则 //程序输出 81F:若用户输入96 F,则程序输出36 C(其中C代表摄氏温度,F代表华氏温度),华氏温度与摄氏温度转化的公式为: //C = 5 (F - 32) / 9 //F = 9 C / 5 + 32 //要求输入的温度值是整数,输出的温度值也是四舍五入后的整数. package 第三天_练习

JSON数据转化成模型

JSON数据转化成模型 // 1.创建url NSURL *url = kSUNUrl(@"video"); // 2.创建request NSURLRequest *request = [NSURLRequest requestWithURL:url]; // 3.发送请求数据 NSOperationQueue *queue = [NSOperationQueue mainQueue]; [NSURLConnection sendAsynchronousRequest:request

如何将别人的知识转化成自己的知识?

不传授具体的知识,只告诉你获得知识的方法.将别人的知识转化成自己的知识,成就你的丰盈人生! 由知识管理中心(Knowledge Management Center)基于最新知识管理理论和实践.认知与学习理论,结合互联网对于信息和知识整合.传播.创造的影响所开发的"KMC高效学习方法网络课程"已经在众多同学学习的基础上.结合多位专家的建议进行了重大升级. [课程名称]KMC 高效学习方法网络课程–互联网思维下的高效学习方法 [课程导师]田志刚 知名知识管理专家.个人知识管理畅销书<

UVA 11054 The Necklace 转化成欧拉回路

题意比较简单,给你n个项链碎片,每个碎片的两半各有一种颜色,最后要把这n个碎片串成一个项链,要求就是相邻碎片必须是同种颜色挨着. 看了下碎片总共有1000个,颜色有50种,瞬间觉得普通方法是无法在可控时间内做出来的,因为碎片到底放哪里以及是正着放还是反着放都是不可控的. 这个时候数学建模就真的好重要了,如果我们能把颜色作为节点,一个碎片就表示两个节点连了一条路,那其实就是走了一遍欧拉回路,就意味着项链做成了. 太叼了,这个思想真心不错...LRJ书上的提示,否则我还真是想不到可以这样. 不过还有

新手学习算法----二叉树(将一个二叉查找树按照中序遍历转换成双向链表)

题目:将一个二叉查找树按照中序遍历转换成双向链表. 给定一个二叉查找树: 4 / 2 5 / 1 3 返回 1<->2<->3<->4<->5. 思路:如果对于当前节点,把右子树转换成双向链表,然后把左子树转换成双向链表,转换的时候我们都标记了链表的头节点和尾节点,那么只需要将当前节点和左子树的尾部相连,和右子树的头部相连即可. Java代码:这个是借鉴九章里面的解题法.但是对于左右子树转换成二叉树也不是很理解,还待需要继续分析. /** * Definit

laravel 将数组转化成字符串 再把字符串转化成数组

这是在给阮少翔改代码的时候用的方法, 开始的数据用explored转化成数组不是想要的结果, 我就自己写了一个方法把有用的信息提取出来拼接成一个字符串, 再用explored将字符串转化成数组.   方法有点笨, 但是最后是解决了阮少翔的问题 $re1 = DB::table('admin_user') ->join('admin_role_user','admin_user.id','=','admin_role_user.user_id') ->select('admin_role_use

( # #@ ## 在define中的应用)或( 连接两个字符串或者两个数字、强制转化成单引号、强制转化成双引号 )附加字符串强制转化成数字

1. 修改成常用的几个连接表示L与x连接. 以下来自网络:#define Conn(x,y) x##y#define ToChar(x) #@x#define ToString(x) #x x##y表示什么?表示x连接y,举例说:int n = Conn(123,456); 结果就是n=123456;char* str = Conn("asdf", "adf")结果就是 str = "asdfadf";怎么样,很神奇吧 再来看#@x,其实就是给x