昨天笔试这题,回来后自己再折腾一下午还是没有独自解决,思路肯定是用递归,可就是有个指针的指向问题让我特别老火。好吧,承认自己算法很菜了,之前做题太少,现在知道痛苦了。出来混,迟早都是要还的。。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);
}
原文地址: