线索树的建立与遍历

在建立二叉树的时候发现,那些叶节点的左孩子和右孩子的指针域都是空的,浪费空间,这时候就可以将这些空间利用起来,让遍历更加方便,这就是线索树存在的原因,线索树实现完了之后其实会发现就是一个双向链表,那种遍历就容易的多了。

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3
  4 typedef char ElemType; //数据类型
  5 typedef enum {Link,Thread} childTag; //Link表示结点,Thread表示线索
  6 typedef struct bitNode
  7 {
  8     ElemType data;
  9     struct bitNode *lchild,*rchild;
 10     int ltag,rtag;
 11 } bitNode ,*bitTree;
 12
 13 void create_tree(bitTree *T,char **arr); //创建二叉树
 14 void pre_order_traverse(bitTree T,int level); //前序遍历二叉树
 15 void in_order_threading(bitTree T); //中序遍历线索化
 16 void in_thread(bitTree *P,bitTree T); //新加入一个头结点,让二叉树成一个封闭环
 17 void in_order_traverse(bitTree T); //中序遍历二叉树(带有头结点)
 18 void visit(bitTree T); //访问结点信息
 19
 20 bitTree pre; //表示上次刚刚访问的结点
 21
 22 int main()
 23 {
 24   bitTree P,T;
 25   int level =1; //表示该结点的深度
 26   char *arr="ab d  ce   "; //构造二叉树所需结点(按前序遍历方式输入), 只是实验数据, 也可以从键盘输入
 27   create_tree(&T,&arr); //构造二叉树
 28   printf("pre-order-traverse\n");
 29   pre_order_traverse(T,level); //前序遍历输出二叉树
 30   printf("\nin-order-traverse\n");
 31   in_thread(&P,T); //二叉树线索化
 32   in_order_traverse(P); //输出线索化后的二叉树
 33   return 0;
 34 }
 35
 36 /*
 37 创建二叉树,其输入必须按照前序遍历的次序。
 38 T:二叉树根节点
 39 arr:按照前序遍历次序排列的各节点的值。无孩子结点时用空格代替
 40 */
 41 void create_tree(bitTree *T,char **arr)
 42 {
 43     char c;
 44     sscanf(*arr,"%c",&c); //读入一个结点值
 45     (*arr)++;
 46     if(‘ ‘==c) //如果是空格,表示空结点
 47     {
 48         *T=NULL;
 49     }
 50     else
 51     {
 52         *T=(bitTree)malloc(sizeof(bitNode)); //构造新结点
 53         (*T)->data=c;
 54         (*T)->ltag=Link;
 55         (*T)->rtag=Link;
 56         create_tree(&(*T)->lchild,arr);//构造新结点的左孩子
 57         create_tree(&(*T)->rchild,arr);//构造新结点的右孩子
 58     }
 59 }
 60
 61 /*
 62 前序遍历访问二叉树
 63 */
 64 void pre_order_traverse(bitTree T,int level)
 65 {
 66     if(T)
 67     {
 68         visit(T);
 69         pre_order_traverse(T->lchild,level+1);
 70         pre_order_traverse(T->rchild,level+1);
 71     }
 72 }
 73
 74 /*
 75 中序遍历二叉树,对其进行线索化
 76 */
 77 void in_order_threading(bitTree T)
 78 {
 79     if(T)
 80     {
 81         in_order_threading(T->lchild); //左孩子线索化
 82         if(!T->lchild) //如果左孩子为空,则将其指向直接前驱
 83         {
 84             T->lchild=pre;
 85             T->ltag=Thread;
 86         }
 87         if(!pre->rchild) //如果上一个结点的右孩子为空,则将其指向直接后继。(注意:只有访问到下一个结点时,才会知道本结点的后继是谁)
 88         {
 89             pre->rchild=T;
 90             pre->rtag=Thread;
 91         }
 92         pre=T;
 93         in_order_threading(T->rchild); //右孩子线索化
 94     }
 95 }
 96
 97 /*
 98 加入一个头结点,使二叉线索树成一个封闭环
 99 P:带有头结点的二叉树。头结点的左孩子指向二叉树T;右孩子指向T树中的最后一个叶子结点
100 T:不带有头结点的二叉树。
101 */
102 void in_thread(bitTree *P,bitTree T)
103 {
104     (*P)=(bitTree)malloc(sizeof(bitNode)); //构造新加入的头结点
105     (*P)->ltag=Link;
106     (*P)->rtag=Thread;
107     (*P)->rchild=*P;
108     if(!T) //如果二叉树为空,则P的孩子指向自己。
109     {
110         (*P)->lchild=*P;
111     }
112     else
113     {
114         (*P)->lchild=T;
115         pre=*P;
116         in_order_threading(T); //对二叉树进行线索化
117         (*P)->rchild=pre; //将头结点右孩子指向最后一个叶子结点
118         pre->rtag=Thread; //将最后一个叶子结点的右孩子指向头结点。这样,环就形成了。
119         pre->rchild=*P;
120     }
121 }
122
123 /*
124 非递归方式:中序遍历二叉树(树必须带有头结点,且已经线索化)
125 P:带有头结点的二叉树
126 */
127 void in_order_traverse(bitTree P)
128 {
129     bitTree T;
130     T=P->lchild;
131     while(T!=P) //判断是否空树
132     {
133         while(T->ltag==Link) //从左孩子开始,直到叶子结点
134         {
135             T=T->lchild;
136         }
137         visit(T);
138         while(T->rtag==Thread && T->rchild!=P) //根据线索,访问后继结点。并且后继结点不是指向头结点的
139         {
140             T=T->rchild;
141             visit(T);
142         }
143         T=T->rchild;
144     }
145 }
146
147 /*
148 访问结点信息
149 */
150 void visit(bitTree T)
151 {
152     printf("%c ",T->data);
153 }
时间: 2024-08-10 19:17:06

线索树的建立与遍历的相关文章

线索二叉树的建立与遍历

线索二叉树利用二叉树空余的指针域,来实现二叉树的链式化.然后,就可以通过前驱,后继像双向链表一样根据某种遍历次序对树的结点进行访问. 数据结构: 1 struct node{ 2 int data; 3 struct node* left,*right; 4 int ltag,rtag; //=0时,表明指向子结点:=1时,表示指向前驱/后继 5 } 建立线索二叉树: 不同的遍历顺序,会得到不同的线索二叉树. 一般使第线索链表的头和尾指向NULL(也可以加入一个头指针) 以中序遍历为例:(对左子

树的建立和遍历

二叉树的建立 typedef struct node{ int data; struct node *L, *R; }*BiTree; 前中建树 //给出当前先序序列PreL, PreL+1, ..., Pre(L+numLeft), Pre(L+numLeft+1), ..., PreR //给出当前中序序列InL, InL+1, ..., In(K-1), InK, In(k+1), ..., InR BiTree PreInCreate(int preL, int preR, int in

数据结构与算法 3:二叉树,遍历,创建,释放,拷贝,求高度,面试,线索树

[本文谢绝转载,原文来自http://990487026.blog.51cto.com] 树 数据结构与算法 3:二叉树,遍历,创建,释放,拷贝,求高度,面试,线索树 二叉树的创建,关系建立 二叉树的创建,关系建立2 三叉链表法 双亲链表: 二叉树的遍历 遍历的分析PPT 计算二叉树中叶子节点的数目:使用全局变量计数器 计算二叉树中叶子节点的数目:不使用全局变量计数器 无论是先序遍历,中序遍历,后序遍历,求叶子的数字都不变;因为本质都是一样的,任何一个节点都会遍历3趟 求二叉树的高度 二叉树的拷

二叉线索树-创建中序二叉线索树、查找前驱、查找后继、按照前驱或后继遍历

#include <iostream> #include <stack> using namespace std; struct BiThrNode { int data; BiThrNode *left; BiThrNode *right; bool ltag;//0表示left指向左子,1表示left指向直接前驱 bool rtag; //BiThrNode(int val,BiThrNode *l,BiThrNode *r,bool lt,bool rt):data(val)

算法学习 - 表达树的建立(后缀表达式法),树的先序遍历,中序遍历,后序遍历

表达树就是根据后缀表达式来建立一个二叉树. 这个二叉树的每个叶子节点就是数,真祖先都是操作符. 通过栈来建立的,所以这里也会有很多栈的操作. 树的先序遍历,中序遍历,后序遍历的概念我就不讲了,不会的自行百度,不然也看不懂我的代码. 下面是代码: // // main.cpp // expressionTree // // Created by Alps on 14-7-29. // Copyright (c) 2014年 chen. All rights reserved. // #includ

C# TreeView 建立、遍历树(递归)

刚接触treeview这个功能,恶补了几天,博主总结下实现的功能以备用,希望能帮到需要的亲~~ C#gui程序中建立树状结构.遍历树状结构.树状结构节点选中联动(选中父节点时,自动选中其全部子节点,取消选中的某子节点,取消其相应的所有父节点的选中),读取选中节点信息. 0.最初的父节点建立ParentNode = tv_user.Nodes.Add(OUname);tv_user.CheckBoxes = true; //表示节点可以进行选中/取消选中操作121.增加树的子节点写了一个函数,(递

hiho #1014 : Trie树 (字典树的建立和查找)

#1014 : Trie树 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一本词典,于是小Hi就向小Ho提出了那个经典的问题:"小Ho,你能不能对于每一个我给出的字符串,都在这个词典里面找到以这个字符串开头的所有单词呢?" 身经百战的小Ho答道:"怎么会不能呢!你每给我一个字符串,我就依次遍历词典里的所有

C语言二叉树的建立与遍历

二叉树的建立和遍历都要用到递归,先暂时保存一下代码,其中主要是理解递归的思想,其它的就都好理解了.这里是三种遍历方式,其实理解一种,其它的几个就都理解了,就是打印出来的顺序不一样而已.建立和遍历的方式差不多.也分好几种方式建立,这里 就写一种,就是先序建立 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 typedef struct TreeNode{ 5 char ch; 6 struct TreeNode *lchild, *rch

二叉线索树

线索化是为了能够像链表一样遍历树. 线索化概念 1.前言 普通二叉树只能找到结点的左右孩子信息,而该结点的直接前驱和直接后继只能在遍历过程中获得. 若可将遍历后对应的有关前驱和后继预存起来,则从第一个结点开始就能很快“顺藤摸瓜”而遍历整个树了. 二叉线索树思想是干什么的? 中序遍历这棵树===>转换成链表访问 2线索化思想 结论:线索化过程就是在遍历过程(假设是中序遍历)中修改空指针的过程: 将空的lchild改为结点的直接前驱: 将空的rchild改为结点的直接后继. 3线索化思想训练 请将此