zoukankan      html  css  js  c++  java
  • 【经典数据结构算法】(1)二叉查找树与双向链表之间的转换

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

      1 /*
    2 * 将二元查找树转变为排序的双向链表
    3 * 题目:输入一颗二元查找树,将该二元查找树转换成一个排序的双向链表
    4 * 要求不能创建任何新的结点,只调整指针的指向。
    5 * 如:
    6 * 10
    7 * / \
    8 * 6 14
    9 * / \ / \
    10 * 4 8 12 16
    11 *
    12 * 转换成:4=6=10=12=16
    13 *
    14 */
    15 // [10/1/2011 Chenny]
    16 /*
    17 * 分析:
    18 * 二元查找树实质上是这样的一种二叉树:每个结点的值均小于左子结点的值,而大于右子结点的值。
    19 * 要让二元查找树转换成排序的双向链表而不创建任何结点,就需要斟酌考虑如何调整结点之间的指针。
    20 * 在二元查找树中,最小的值一定是最左结点,其次是最左节点的父节点,再次是该父节点的右子结点(如果存在的话)。
    21 * 最大的结点与最小的结点相似,只是左右颠倒:最大的值一定是最右结点……
    22 * 通过分析二元查找树的结点的连接情况,可以很显然地知道,如果要按照顺序遍历它,就是那种最基本的遍历:前序遍历(先序遍历)。
    23 * 那么就通过最基本的前序遍历方法:递归来实现。
    24 * 接下来最重要的一件事情就是如何调整相关联的两个结点指针。下面考虑如何调整指针。
    25 * 在处理一个结点,将它从二元查找树上“弄到”双向链表上的时候,它已经没有了左孩子,否则,就不应该在这个时候处理该结点。
    26 * 而应该去处理它的左子结点。那么,在处理该结点的时候,我们应该怎么做呢?最简单的方法就是创建一个结点指针
    27 * 注意,不是结点,而是指针,这样才符合题目要求。它指向双向链表的最后一个元素,用来将二元查找树中的元素摘下,放到双向链表中。
    28 * 记得在放到双向链表中的时候,不要处理该结点的右子指针,因为我们还没有处理过比它大的结点。
    29 * 以上即是基本的分析,下面用程序来实现
    30 */
    31 #include <StdAfx.h>
    32 #include <stdlib.h>
    33 #include <stdio.h>
    34 /*
    35 * 定义二叉树的结构
    36 */
    37 typedef struct TreeNode *link;
    38 struct TreeNode
    39 {
    40 int value;
    41 link LeftChild;
    42 link RightChild;
    43 };
    44 /*
    45 * list为双向排序链表
    46 */
    47 link list=NULL;
    48 /*
    49 * 定义结点初始化函数,用来方便生成树
    50 */
    51 link initNode(int i)
    52 {
    53 link t=(link)malloc(sizeof(*t));
    54 t->value=i;
    55 t->LeftChild=NULL;
    56 t->RightChild=NULL;
    57 return t;
    58 }
    59 /*
    60 * visit函数递归调用,前序遍历二元查找树的每一个结点
    61 * 并在适当的时候,将结点插入到双向排序链表中
    62 */
    63 void visit(link t)
    64 {
    65 /*
    66 * 递归左子
    67 */
    68 if(t->LeftChild!=NULL)
    69 {
    70 visit(t->LeftChild);
    71 }
    72 /*
    73 * 处理当前结点
    74 */
    75 if(list==NULL) //说明当前结点是最小的结点
    76 {
    77 list=t;
    78 t->LeftChild=NULL;
    79 }
    80 else //list已经非空
    81 {
    82 list->RightChild=t;
    83 t->LeftChild=list;
    84 list=t;
    85 }
    86 /*
    87 * 递归右子
    88 */
    89 if(t->RightChild!=NULL)
    90 {
    91 visit(t->RightChild);
    92 }
    93 }
    94 int main(void)
    95 {
    96 /*
    97 * 产生测试数据
    98 */
    99 link root=initNode(10);
    100 root->LeftChild=initNode(6);
    101 root->RightChild=initNode(14);
    102 root->LeftChild->LeftChild=initNode(4);
    103 root->LeftChild->RightChild=initNode(8);
    104 root->RightChild->LeftChild=initNode(12);
    105 root->RightChild->RightChild=initNode(16);
    106 visit(root);
    107 printf("下面开始逆序输出:\n");
    108 while(list->LeftChild!=NULL)
    109 {
    110 printf("%d\t",list->value);
    111 list=list->LeftChild;
    112 }
    113 printf("%d\n",list->value);
    114
    115 printf("下面开始正序输出:\n");
    116 while(list->RightChild!=NULL)
    117 {
    118 printf("%d\t",list->value);
    119 list=list->RightChild;
    120 }
    121 printf("%d\n",list->value);
    122 return 0;
    123 }

    测试数据的结果:


    作者:Chenny Chen
    出处:http://www.cnblogs.com/XjChenny/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    离奇的软件开发之路
    集群环境中的单例设计模式
    Android 如何更换屏幕上锁界面背景图片
    基于华为Java编程规范的Eclipse checkStyle.xml
    对数据库事务的总结
    [Sciter系列] MFC下的Sciter–1.创建工程框架
    Android 如何添加一种锁屏方式
    Hibernate级联操作 注解
    linux就是这个范儿之融于心而表于行(1)
    Android 如何修改默认的searchable items。
  • 原文地址:https://www.cnblogs.com/XjChenny/p/2197783.html
Copyright © 2011-2022 走看看