您的位置:首页 > 理论基础 > 数据结构算法

【经典数据结构算法】(1)二叉查找树与双向链表之间的转换

2011-10-01 21:15 507 查看
题目参看csdn上的一个很经典的帖子,http://topic.csdn.net/u/20101126/10/b4f12a00-6280-492f-b785-cb6835a63dc9.html?60918。但代码都是自己使用C语言写的,思路基本上都是自己想出的,如果参考了帖子上别人的思想,则会注明。

/*
*    将二元查找树转变为排序的双向链表
*    题目:输入一颗二元查找树,将该二元查找树转换成一个排序的双向链表
*    要求不能创建任何新的结点,只调整指针的指向。
*        如:
*                10
*                / \
*               6   14
*              / \  / \
*             4  8 12 16
*
*        转换成:4=6=10=12=16
*
*/
//  [10/1/2011 Chenny]
/*
*    分析:
*    二元查找树实质上是这样的一种二叉树:每个结点的值均小于左子结点的值,而大于右子结点的值。
*    要让二元查找树转换成排序的双向链表而不创建任何结点,就需要斟酌考虑如何调整结点之间的指针。
*    在二元查找树中,最小的值一定是最左结点,其次是最左节点的父节点,再次是该父节点的右子结点(如果存在的话)。
*    最大的结点与最小的结点相似,只是左右颠倒:最大的值一定是最右结点……
*    通过分析二元查找树的结点的连接情况,可以很显然地知道,如果要按照顺序遍历它,就是那种最基本的遍历:前序遍历(先序遍历)。
*    那么就通过最基本的前序遍历方法:递归来实现。
*    接下来最重要的一件事情就是如何调整相关联的两个结点指针。下面考虑如何调整指针。
*    在处理一个结点,将它从二元查找树上“弄到”双向链表上的时候,它已经没有了左孩子,否则,就不应该在这个时候处理该结点。
*    而应该去处理它的左子结点。那么,在处理该结点的时候,我们应该怎么做呢?最简单的方法就是创建一个结点指针
*    注意,不是结点,而是指针,这样才符合题目要求。它指向双向链表的最后一个元素,用来将二元查找树中的元素摘下,放到双向链表中。
*    记得在放到双向链表中的时候,不要处理该结点的右子指针,因为我们还没有处理过比它大的结点。
*    以上即是基本的分析,下面用程序来实现
*/
#include <StdAfx.h>
#include <stdlib.h>
#include <stdio.h>
/*
*    定义二叉树的结构
*/
typedef struct TreeNode *link;
struct TreeNode
{
int value;
link LeftChild;
link RightChild;
};
/*
*    list为双向排序链表
*/
link list=NULL;
/*
*    定义结点初始化函数,用来方便生成树
*/
link initNode(int i)
{
link t=(link)malloc(sizeof(*t));
t->value=i;
t->LeftChild=NULL;
t->RightChild=NULL;
return t;
}
/*
*    visit函数递归调用,前序遍历二元查找树的每一个结点
*    并在适当的时候,将结点插入到双向排序链表中
*/
void visit(link t)
{
/*
*    递归左子
*/
if(t->LeftChild!=NULL)
{
visit(t->LeftChild);
}
/*
*    处理当前结点
*/
if(list==NULL)  //说明当前结点是最小的结点
{
list=t;
t->LeftChild=NULL;
}
else   //list已经非空
{
list->RightChild=t;
t->LeftChild=list;
list=t;
}
/*
*    递归右子
*/
if(t->RightChild!=NULL)
{
visit(t->RightChild);
}
}
int main(void)
{
/*
*    产生测试数据
*/
link root=initNode(10);
root->LeftChild=initNode(6);
root->RightChild=initNode(14);
root->LeftChild->LeftChild=initNode(4);
root->LeftChild->RightChild=initNode(8);
root->RightChild->LeftChild=initNode(12);
root->RightChild->RightChild=initNode(16);
visit(root);
printf("下面开始逆序输出:\n");
while(list->LeftChild!=NULL)
{
printf("%d\t",list->value);
list=list->LeftChild;
}
printf("%d\n",list->value);

printf("下面开始正序输出:\n");
while(list->RightChild!=NULL)
{
printf("%d\t",list->value);
list=list->RightChild;
}
printf("%d\n",list->value);
return 0;
}


测试数据的结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: