把二元查找树转变成排序的双向链表

图灵DUCK 2013-09-06 12:00:29
(一)把二元查找树转变成排序的双向链表

输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只调整指针的指向。 比如将二元查找树
10
/ \
6 14
/ \ /  \
4 8 12  16
转换成双向链表

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

分析:本题是微软面试100题的第一题,由于树本身定义就属于递归式定义,所以很多与树相关的题目都是用递归的思路来解决,本题亦是如此。下面我们用两种不同的递归思路来分析。

思路一:中序遍历的顺序即是我们所要建立链表的顺序。所以可以在中序遍历整棵树的同时,通过调整节点的指针来将其转换为双向链表。当所有结点都访问过之后,整棵树也就转换成一个排序双向链表了。

思路二:当我们到达某一结点准备调整以该结点为根结点的子树时,先调整其左子树,将左子树转换成一个排好序的左子链表,再调整其右子树转换右子链表。最后链接左子链表的最右结点(左子树的最大结点)、当前结点和右子链表的最左结点(右子树的最小结点)。从树的根结点开始递归调整所有结点。

#include<stdio.h>
#include<stdlib.h>
struct BiTreeNode
{
int value;
BiTreeNode *left;
BiTreeNode *right;
};

void Convert(BiTreeNode *& head, BiTreeNode *& tail, BiTreeNode *root)
{
BiTreeNode *left, *right;
if (root == NULL)
{
head = NULL;
tail = NULL;
return;
}
Convert(head, left, root->left);
Convert(right, tail, root->right);
if (left!=NULL)
{
left->right = root;
root->left = left;
}
else
{
head = root;
}
if (right!=NULL)
{
root->right=right;
right->left = root;
}
else
{
tail = root;
}

}

BiTreeNode * treeToLinkedList(BiTreeNode * root)
{
BiTreeNode * head, * tail;
Convert(head, tail, root);
return head;//返回链表的头指针
}

/*递归创建二叉排序树,以'-1'结束*/
BiTreeNode * CreateBSTree()
{
int data;
BiTreeNode * tr;
scanf("%d",&data);
if(data==-1)
{
return NULL;
}
else
{
tr = (BiTreeNode *)malloc(sizeof(BiTreeNode));
tr->value=data;
tr->left = CreateBSTree();
tr->right = CreateBSTree();

return tr;
}
}

//中序遍历二叉树
void InOrderTraverse(BiTreeNode * root)
{
if(root->left)
InOrderTraverse(root->left);

if(root)
printf("%d ",root->value);

if(root->right)
InOrderTraverse(root->right);
}
int main()
{
BiTreeNode * root=CreateBSTree();

InOrderTraverse(root);
printf("\n");

BiTreeNode *head=treeToLinkedList(root);

BiTreeNode * temp=head;
while(temp!=NULL)
{
printf("%d ",temp->value);
temp=temp->right;
}

getchar();
return 0;
}



Convert函数里的left和right怎么理解,不是一直为null吗?
...全文
143 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
modyaj 2013-09-09
  • 打赏
  • 举报
回复
引用 4 楼 u010948424 的回复:
已经理解了~~~感谢
恭喜
图灵DUCK 2013-09-08
  • 打赏
  • 举报
回复
已经理解了~~~感谢
modyaj 2013-09-06
  • 打赏
  • 举报
回复
建议楼主画图来理解 多动动手 会更容易懂 左子树 如题目图上 4 6 12 右子树 8 14 1等就不是空 代码的意思无外乎就是先找到最左边节点和最右边节点 很明显 4 下面没有节点了 4 就是最左边的节点 作为根 递归的话 先看 4 6 8 这个子树 8是最右边的 作为 尾巴 。。。 4 6 8 最为整体在10的左边 那么 12 14 16 在10的右边作为尾巴 那么 10 就在 左和右的中间 得到 4 6 8 10 后面的和左子树一样一样的 最后 Convert函数里的left和right并不一直是空 是空的时候就返回去了 递归到上一层处理
WizardOz 2013-09-06
  • 打赏
  • 举报
回复
这个是C++代码,不是C语言代码。 Convert函数的参数是引用,所以传递到Convert函数的参数可以被改变。 另外left和right的定义为初始化,不太好。 我觉得这是一个很差的代码。1.看上去像C语言,其实是C++。2.指针变量未初始化直接使用。3.不想往下看了
图灵DUCK 2013-09-06
  • 打赏
  • 举报
回复
学过一些C和JAVA可是现在都发现分不清好的代码和不好的代码。。。

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧