【经典数据结构算法】(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; }
测试数据的结果:
相关文章推荐
- 【经典数据结构算法】(1)二叉查找树与双向链表之间的转换
- 二叉查找树转换成有序的双向链表
- 二叉查找树转换为顺序的双向链表
- 二叉树的中序遍历,以及与双向链表之间的转换
- 二叉查找树转换为双向链表
- 二叉查找树转换为有序双向链表
- 二进制数 八进制数 十进制数 十六进制数 之间的相互转换!!!!
- C# 实现16进制和字符串之间转换的代码[转]
- ArrayList与数组之间相互转换
- Int,Float,Char *,CString之间的转换
- dataset和实体类 之间的转换
- C#对象与XMl文件之间的相互转换(转)
- Android中Drawable和Bitmap 之间转换
- android dp和px之间转换
- 进制之间的转换
- 转:CString,int,string,char*之间的转换
- c++中的char*与wchar_t*与string以及wstring之间的相互转换
- CString,string,char *,int之间的转换
- 字符串和字符数组之间的转换
- 使用Gson或者GsonBuilder实现JSON和Java对象之间的转换