将二叉查找树转换成有序的双向链表

1 分钟读完

题目

输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。

要求不能创建任何新的结点,只调整指针的指向。

10
/  \
6   14
/ \   / \
4  8 12 16

转换成双向链表

4=6=8=10=12=14=16。

分析

二叉查找树有一个性质:

一个节点的左子树上所有节点的值均小于该节点的值,并且在图上观看就是左子树上有最大值的节点在最右侧

一个节点的右子树上的所有节点的值均大于该节点的值,并且在图上观看就是右子树上有最小值的节点在最左侧

用递归的思想,将一个节点A的左右子树分别变成双向链表,返回左子树的最大值节点Aleft和右子树的最小值节点Aright,最后将A、Aleft和Aright的指针连接起来。

代码

/*
author:SwordStraw

http://onestraw.net

*/
#include<stdio.h>
#include<stdlib.h>
//搜索二叉树节点
typedef struct BSTreeNode{
	int cargo;
	BSTreeNode *left;
	BSTreeNode *right;
}BSTreeNode;

//深度优先建树,假定该树的所有节点值均为正数, 输入负数和0表示回上一层父结点
BSTreeNode* createBSTree(int high)
{
	BSTreeNode *root;
	root = NULL;
	int value;
	printf("第%d层, 请输入节点的值: ", high);
	scanf("%d", &value);
	if(value > 0)
	{
		root = (BSTreeNode*)malloc(sizeof(BSTreeNode));
		root->cargo = value;
		root->left = createBSTree(high+1);
		root->right = createBSTree(high+1);
	}
	return root;
}

//返回二叉树的最右侧节点
BSTreeNode *rightOfTree(BSTreeNode *root)
{
	BSTreeNode *p;
	p = root;
	while(p && p->right)
		p = p->right;
	return p;
}
//返回二叉树的最左侧节点
BSTreeNode *leftOfTree(BSTreeNode *root)
{
	BSTreeNode *p;
	p = root;
	while(p && p->left)
		p = p->left;
	return p;
}
//把二叉搜索树转换成双向链表
//left指针指向驱节点,right指针指向后继节点
void ConvertToDulLinkList(BSTreeNode *cur)
{
	BSTreeNode *lchild, *rchild;
	lchild = rchild = NULL;
	if(cur->left)
	{
		ConvertToDulLinkList(cur->left);
		lchild = rightOfTree(cur->left);//左子树最大的
	}
	if(cur->right)
	{
		ConvertToDulLinkList(cur->right);
		rchild = leftOfTree(cur->right);//右子树最小的
	}
	if(lchild)
	{
		lchild->right= cur;
		cur->left=lchild;
	}
	if(rchild)
	{
		rchild->left=cur;
		cur->right=rchild;
	}
}
//遍历双向链表
//direction表示方向,0表示从后向前,1表示从前向后
void traverseTree(BSTreeNode *head, int direction)
{
	while(head)
	{
		printf("%d->",head->cargo);
		if(direction == 1)
			head = head->right;
		else if(direction == 0)
			head = head->left;
	}
	printf("\n");
}
//测试程序 
int main(int argc, char *argv[])
{
	printf("[深度优先建树, 假定该树的所有节点值均为正数, 输入负数和0表示回上一层父结点]\n");
	BSTreeNode *root;
	/*构造如下一棵二叉搜索树
	10
   /  \
  6    14
 / \   / \
4   8 12 16
	
	如果嫌输入麻烦,可直接将下面粘贴到命令行:10 6 4 0 0 8 0 0 14 12 0 0 16 0 0
	*/
	root = createBSTree(0);
	BSTreeNode *head, *tail;//链表的头和尾
	head = leftOfTree(root);
	tail = rightOfTree(root);

	ConvertToDulLinkList(root);
	printf("\n双向遍历\n");
	traverseTree(head,1);
	traverseTree(tail,0);
	return 0;
}

留下评论