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

昨天笔试这题,回来后自己再折腾一下午还是没有独自解决,思路肯定是用递归,可就是有个指针的指向问题让我特别老火。好吧,承认自己算法很菜了,之前做题太少,现在知道痛苦了。出来混,迟早都是要还的。。OK,直接记录,在此感谢原文博主。

题目:

       将一棵排序二叉树转换成排序的双向链表,不增加新的结点,只调整指针方向

思路:

       基本凡是牵涉到二叉树的,递归绝对是首先应该想到的方法,此题不例外

我的问题:

       一图胜千言:

                            

解决:

        遍历的时候,需要带上指向尾结点的指针。我独自做的时候,也想到是需要有一个额外的指针指向前一个结点的,但是我考虑的这个指针并不知道是尾结点指针,所以考虑了很多情况,反而复杂了。图示:

                   

代码我自己再实现了一遍,但就是原文的再现,代码如下:

/* 排序二叉树转双链表 */
#include <stdio.h>
#include <stdlib.h>

typedef struct listnode
{
	int key;
	struct listnode *left, *right;
}Node_S;

/* 创建排序二叉树 */
void CreatSortTree(Node_S **ptr, int data)			// 传指针其实质是传值,然后在本函数中进行一份地址拷贝。
{									// 如果传单指针,此函数中malloc分配的内存就并不是指给
	if (NULL == (*ptr))				// 被调函数传进的地址,而是本函数中的拷贝后的地址,
	{								// 如果传双指针,虽然同样是做地址拷贝,但malloc分配后是
		(*ptr) = (Node_S *)malloc(sizeof(Node_S));    // 指给这个拷贝地址上的内容,而主调函数传进来的地址与本
		(*ptr)->key = data;					// 函数拷贝后地址上的内容是一致的,这就是用双指针的原因
		(*ptr)->left = NULL;
		(*ptr)->right = NULL;
		return;
	}
	else if (data < (*ptr)->key)
	{
		return CreatSortTree(&(*ptr)->left, data);
	}
	else if (data > (*ptr)->key)
	{
		return CreatSortTree(&(*ptr)->right, data);
	}
	else
	{
		return;
	}
}

/* 中序遍历 */
void InOrderTravel(Node_S *ptr)
{
	if(NULL == ptr)
	{
		return ;
	}

	InOrderTravel(ptr->left);
	printf("%d ",ptr->key);
	InOrderTravel(ptr->right);
}

/* 二叉树转双链表 */
void Btree2Blink(Node_S *root, Node_S **listhead, Node_S **listtail)
{
	if (NULL == root)
	{
		return;
	}

	Btree2Blink(root->left, listhead, listtail);

	/* 关键部分 */
	root->left = *listtail; //我疑惑的问题所在,答案很简单,但自己就是没想出来
	if(NULL != *listtail)
	{
		(*listtail)->right = root; 
	}
	else 
	{
		*listhead = root; 
	}
	*listtail = root; 

	Btree2Blink(root->right, listhead, listtail);
}

/* 打印 */
void PrintList(Node_S *listhead, Node_S *listtail)
{
	Node_S *ptr = NULL;

	printf("\n");
	while (listhead != NULL)
	{
		printf("[%d] ",listhead->key);
		listhead = listhead->right;
	}

	printf("\n");

	while (listtail != NULL)
	{
		printf("[%d] ",listtail->key);
		listtail = listtail->left;
	}
	printf("\n");
}
void main()
{
	int i = 0;
	int data[] = {4,9,3,6,23,11,8,34,78};
	Node_S *proot = NULL;
	Node_S *ListHead = NULL;
	Node_S *ListTail = NULL;

	/* 创建排序二叉树 */
	for (i = 0; i < sizeof(data)/sizeof(int); i++)
	{
		CreatSortTree(&proot, data[i]);
	}
	
	/* 中序遍历下,查下结果 */
	InOrderTravel(proot);

	/* 二叉树转双链表 */
	Btree2Blink(proot, &ListHead, &ListTail);

	/* 打印链表 */
	PrintList(ListHead, ListTail);
}

 

原文地址:

http://m.blog.youkuaiyun.com/blog/kuzuozhou/8016238

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值