二叉树的链式存储结构----(循环)双向线索链表

来源:互联网 发布:linux安装discuz论坛 编辑:程序博客网 时间:2024/05/17 08:35


头文件:head.h

#ifndef _HEAD_1_H_#define _HEAD_1_H_#include<string.h>#include<ctype.h>#include<malloc.h> /* malloc()等 */#include<limits.h> /* INT_MAX等 */#include<stdio.h> /* EOF(=^Z或F6),NULL */#include<stdlib.h> /* atoi() */#include<io.h> /* eof() */#include<math.h> /* floor(),ceil(),abs() */#include<process.h> /* exit() *//* 函数结果状态代码 */#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1/* #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行 */typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */#define CHAR//定义字符型//#define INT//定义整型(二选一)#ifdef CHARtypedef char TElemType;//TElemType Nil = ' ';//字符型以空格为空#define form "%c"//输出输出的格式为%c#endif#ifdef INTtypedef int Elemtype;//TElemType Nil = 0;//整型以0为空#define form "%d"//输入输出格式为%d#endiftypedef enum PointerTag{Link, Thread}PointerTag;//Link==0代表指针;Thread==1代表线索typedef struct BiThrNode{TElemType data;struct BiThrNode *lchild, *rchild;//左右孩子指针PointerTag LTag, RTag;//左右标志}BiThrNode, *BiThrTree;Status InitBiThrTree(BiThrTree *T);Status CreateBiThrTree(BiThrTree *T);void InThreading(BiThrTree p);Status InOrderThreading(BiThrTree *Thrt, BiThrTree T);Status InOrderTraverse_Thr(BiThrTree T, Status(*Visit)(TElemType));#endif

算法实现:

#include"head.h"#ifdef CHARTElemType Nil = ' ';#elseTElemType Nil = 0;#endifStatus InitBiThrTree(BiThrTree *T){*T = NULL;return OK;}Status CreateBiThrTree(BiThrTree *T){//按照先序输入二叉树线索中结点的值,构造二叉线索数T//0(整型)/空格(字符型)表示空节点TElemType h;#ifdef CHARscanf_s("%c", &h);#elsescanf_s("%d", &h);#endifif (h == Nil)*T = NULL;else{*T = (BiThrTree)malloc(sizeof(BiThrNode));if (!(*T)){printf("建立二叉树失败!");system("pause");exit(-1);}(*T)->data = h;CreateBiThrTree(&(*T)->lchild);//构造左子树if ((*T)->lchild)//左子树存在(*T)->LTag = Link;CreateBiThrTree(&(*T)->rchild);if ((*T)->rchild)//右孩子存在(*T)->RTag = Link;}return OK;}BiThrTree pre;//全局变量,始终指向刚刚访问过的结点/*由于线索化的实质是将二叉链表中的空指针改为指向前驱或后继的线索,而前驱或后继的信息只有在遍历事才看得到,因此线索化的过程即为在遍历的过程中修改空指针的过程。为了几下遍历过程中访问节点的先后关系,附设一个指针pre始终指向刚刚访问过的结点,若指针p指向当前访问的结点,则pre指向它的前驱。*/void InThreading(BiThrTree p){//中序遍历进行中序线索化if (p){InThreading(p->lchild);//递归左子树线索化if (!p->lchild)//没有左孩子{p->LTag = Thread;//前驱线索p->lchild = pre;//左孩子指针指向前驱,pre代表刚刚访问过的结点,即前驱}if (!p->rchild)//没有右孩子{pre->RTag = Thread;//后继线索pre->rchild = p;//前驱右孩子指针指向后继(当前结点p)}pre = p;//保持pre指向p的前驱InThreading(p->rchild);//递归右子树线索化}}Status InOrderThreading(BiThrTree *Thrt, BiThrTree T){//中序遍历二叉树T,并将其中序线索化,Thrt是头指针,其指向头结点*Thrt = (BiThrTree)malloc(sizeof(BiThrNode));if (!(*Thrt)){printf("中序遍历线索化失败!");system("pause");exit(OVERFLOW);}(*Thrt)->LTag = Link;//建立头结点(*Thrt)->RTag = Thread;(*Thrt)->rchild = *Thrt;//右指针回指if (!T)//若二叉树为空,则左指针回指(*Thrt)->lchild = *Thrt;else{(*Thrt)->lchild = T;//头结点的左孩子指向二叉链表pre = *Thrt;//定义刚刚访问过的结点InThreading(T);//中序遍历进行中序线索化pre->rchild = *Thrt;//最后一个结点线索化pre->RTag = Thread;(*Thrt)->rchild = pre;}return OK;}Status InOrderTraverse_Thr(BiThrTree T, Status(*Visit)(TElemType)){ //T指向头结点,头结点的左链lchild指向根节点,//中序遍历二叉树线索树T的非递归算法,对每个数据元素调用函数visitBiThrTree p;p = T->lchild; /* p指向根结点 */while (p != T){ /* 空树或遍历结束时,p==T */while (p->LTag == Link)p = p->lchild;if (!Visit(p->data)) /* 访问其左子树为空的结点 */return ERROR;while (p->RTag == Thread&&p->rchild != T){p = p->rchild;Visit(p->data); /* 访问后继结点 */}p = p->rchild;}return OK;}

测试文件:

#include"head.h"Status vi(TElemType c){#ifdef CHARprintf("%c ", c);#elseprintf("%d ", c);#endifreturn OK;}void main(){BiThrTree H, T;#ifdef CHARprintf("请按先序输入二叉树(如:ab三个空格表示a为根结点,b为左子树的二叉树)\n");#elseprintf("请按先序输入二叉树(如:1 2 0 0 0表示1为根结点,2为左子树的二叉树)\n");#endifCreateBiThrTree(&T); /* 按先序产生二叉树 */InOrderThreading(&H, T); /* 中序遍历,并中序线索化二叉树 */printf("中序遍历(输出)二叉线索树:\n");InOrderTraverse_Thr(H, vi); /* 中序遍历(输出)二叉线索树 */printf("\n");system("pause");}

运行结果:

请按先序输入二叉树(如:ab三个空格表示a为根结点,b为左子树的二叉树)abdg   e  c f中序遍历(输出)二叉线索树:g d b e a c f请按任意键继续. . .


0 0
原创粉丝点击