数据结构与算法笔记 lesson 21 线索二叉树

来源:互联网 发布:时间安排提醒软件知乎 编辑:程序博客网 时间:2024/06/09 16:39

为什么使用线索二叉树


浪费了10*4个字节

使用中序遍历 H D I B E A F C G 可以利用“^”记录该结点的前去后继,节省指针浪费的空间。

如果是这种情况


需要将定义好的结构进行扩容

lchild , ltag , data, rtag, rchild

ltag为0 指向该结点的左孩子,为1时指向该结点的前驱

rtag为0 指向该结点的右孩子,为1时指向该结点的后继

   

线索二叉树的实现

#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stdlib.h>typedef char ElemType;//线索存储标志位//Link(0):表示指向左右孩子的指针//Thread(1):表示指向前驱后继的线索typedef enum {Link,Thread}PointerTag;typedef struct BiThrNode{char data;struct BiThrNode *lchild,*rchild;PointerTag ltag;PointerTag rtag;}BiThrNode,*BiThrTree;//全局变量,始终指向刚刚访问过的结点BiThrTree pre;//创建一棵二叉树,约定用户遵照前序遍历的方式输入数据CreateBiThrTree(BiThrTree *T){char c;scanf("%c", &c);if (' ' == c){*T = NULL;}else{*T = (BiThrNode*)malloc(sizeof(BiThrNode));(*T)->data = c;(*T)->ltag = Link;(*T)->rtag = Link;CreateBiThrTree(&(*T)->lchild);CreateBiThrTree(&(*T)->rchild);}}//中序遍历线索化InThreading(BiThrTree T){if (T){InThreading(T->lchild);//递归左孩子线索化//结点处理if (!T->lchild) //如果该结点没有左孩子,设置ltag为thread,并把lchild指向刚刚访问的结点{T->ltag = Thread;T->lchild = pre;}if (!pre->rchild)//如果上一个的右节点为空,没孩子{pre->rtag = Thread; //设置上一个节点rtag为线索pre->rchild = T;  }pre = T;InThreading(T->rchild);//递归右孩子线索化}}//void InOrderThreading(BiThrTree *p,BiThrTree T){*p = malloc(sizeof(BiThrNode));//头指针(*p)->ltag = Link;(*p)->rtag = Thread;(*p)->rchild = *p;if (!T){(*p)->lchild = *p;}else{(*p)->lchild = T;pre = *p;InThreading(T);pre->rchild = *p;pre->rtag = Thread;(*p)->rchild = pre;}}void visit(char c){printf("%c", c);}//中序遍历二叉树,非递归void InOrderTraverse(BiThrTree T){BiThrTree p;p = T->lchild;while (p!=T)//p=T,头指针等于根节点 空树或者遍历到结束{while (p->ltag == Link)//有左子树{p = p->lchild;//找到最左节点}visit(p->data);while (p->rtag == Thread &&p->rchild != T)//有右子树,并且右节点不指向头{ p = p->rchild;//说明有后继visit(p->data);}p = p->rchild;}}int main(){BiThrTree P, T=NULL;CreateBiThrTree(&T);InOrderThreading(&P,T);printf("中序遍历输出结果为:");printf("\n");InOrderTraverse(P);printf("\n");}


0 0
原创粉丝点击