数据结构学习:利用链表建立二叉树
来源:互联网 发布:linux 当前shell 编辑:程序博客网 时间:2024/04/30 21:29
最初版本:利用链表保存二叉树
不足:浪费指针位置。
二叉树结构体
typedef char TElemType;typedef struct BiTree{ TElemType data; struct BiTree *Lchild,*Rchild;}*BiTree,BiTNode;
每一个结点保存数据,左孩子和右孩子的数据。
创建二叉树
利用前序遍历法输入二叉树,没有的结点用#补全
注意传入的参数 是指向指针的指针 这样才能改变指针的值
c++的话也可以用引用代替
void Create_Bitree(BiTree *T){ //前序输入 TElemType data; scanf("%c",&data); if(data == '#') T = NULL; else{ if(!(*T = (BiTree)malloc(sizeof(BiTNode)))) exit(1); (*T)->data = data; Create_Bitree(&(*T)->Lchild); Create_Bitree(&(*T)->Rchild); }}
前序遍历法遍历树
void Pre_Order(BiTree T){ if(T!=NULL){ printf("%c",T->data); Pre_Order(T->Lchild); Pre_Order(T->Rchild); }}
中序遍历法遍历
void In_Order(BiTree T){ if(T!=NULL){ In_Order(T->Lchild); printf("%c",T->data); In_Order(T->Rchild); }}
后序遍历法遍历
void Post_Order(BiTree T){ if(T!=NULL){ Post_Order(T->Lchild); Post_Order(T->Rchild); printf("%c",T->data); }}
主函数
int main(){ BiTree T; printf("请前序遍历输入树\n"); Create_Bitree(&T); printf("前序输出这个二叉树为:\n"); Pre_Order(T); printf("\n"); printf("中序输出这个二叉树为:\n"); In_Order(T); printf("\n"); printf("后序输出这个二叉树为:\n"); Post_Order(T); printf("\n"); return 0;}
进阶版本:(线索二叉树)
利用空指针位置储存前驱和后续;创造头节点,左孩子为树根,右孩子为中序最末结点(投影最后结点)。
结构体中加入Tag位保存是否该指针指向子结点。
若为Link则指向子结点,若为Thread则指向前驱或后续结点。
中序排序第一个(最左孩子)的左指针指向头结点,最后一个(最右孩子)的右指针指向头结点。
结构体创建如下
typedef char TElemType;typedef enum { Link,Thread } PointerTag;typedef struct BiTree{ TElemType data; struct BiTree *Lchild,*Rchild; PointerTag LTag,RTag;}*BiTree,BiTNode;
先来看看主函数
注意头结点由于是连接整个头尾的
所以如果在建立前序后继指针之前创建的话,就会进入死循环。
int main(){ BiTree T,THead; printf("请前序遍历输入树\n"); THead = (BiTree) malloc(sizeof(BiTNode)); Create_Bitree(&T);//创建树 pre = THead; In_Threading(T);//给树加上前驱和后续指针 Create_Head(&THead,T);//创建头结点 printf("中序输出树\n"); In_Order_Traverse(THead);//中序遍历树 printf("\n"); return 0;}
创建输入树时与原先一样
void Create_Bitree(BiTree *T){ //前序输入 TElemType data; scanf("%c",&data); if(data == '#') T = NULL; else{ if(!(*T = (BiTree)malloc(sizeof(BiTNode)))) exit(1); (*T)->data = data; Create_Bitree(&(*T)->Lchild); Create_Bitree(&(*T)->Rchild); }}
令空余指针分别指向前驱和后继结点。
其中pre用来保存上一个结点的信息。
BiTree pre;void In_Threading(BiTree T){ if(T){ In_Threading(T->Lchild); if(!T->Lchild){ T->LTag = Thread; T->Lchild = pre; } if(!pre->Rchild){ pre->RTag = Thread; pre->Rchild = T; } pre = T; In_Threading(T->Rchild); }}
创建头结点
void Create_Head(BiTree *THead,BiTree T){ (*THead)->LTag = Link; (*THead)->Lchild = T;//左孩子指向树根 (*THead)->RTag = Thread; while(T->Rchild->Rchild) T = T->Rchild; T->Rchild->Rchild = (*THead); //最右结点的右孩子指向头结点 T->Rchild->RTag = Thread; (*THead)->Rchild = T; //头结点的右孩子指向最右结点}
遍历函数
void In_Order_Traverse(BiTree T){ BiTree P = T->Lchild; while(P!=T){ while(P->LTag == Link){ P = P->Lchild; }//到达最左孩子 printf("%c",P->data); while(P->RTag == Thread &&P->Rchild !=T){ P = P->Rchild;//后继指针开始起作用了 一路遍历下去。 printf("%c",P->data); }//该结点的左子树遍历完毕 P = P->Rchild;//开始该结点的的右子树 }}
举个例子 各结点保存如下
线索二叉树相较于普通二叉树,其优势在于能更高效的保存信息。 在树中任意一个叶子结点,都可以知道其前驱和后继结点,而不占更多的储存空间。
最后附上完整代码
#include <stdio.h>#include <stdlib.h>typedef char TElemType;typedef enum { Link,Thread } PointerTag;typedef struct BiTree{ TElemType data; struct BiTree *Lchild,*Rchild; PointerTag LTag,RTag;}*BiTree,BiTNode;void Create_Bitree(BiTree *T){ //前序输入 TElemType data; scanf("%c",&data); if(data == '#') T = NULL; else{ if(!(*T = (BiTree)malloc(sizeof(BiTNode)))) exit(1); (*T)->data = data; Create_Bitree(&(*T)->Lchild); Create_Bitree(&(*T)->Rchild); }}BiTree pre;void In_Threading(BiTree T){ if(T){ In_Threading(T->Lchild); if(!T->Lchild){ T->LTag = Thread; T->Lchild = pre; } if(!pre->Rchild){ pre->RTag = Thread; pre->Rchild = T; } pre = T; In_Threading(T->Rchild); }}void In_Order_Traverse(BiTree T){ BiTree P = T->Lchild; while(P!=T){ while(P->LTag == Link){ P = P->Lchild; } printf("%c",P->data); while(P->RTag == Thread &&P->Rchild !=T){ P = P->Rchild; printf("%c",P->data); } P = P->Rchild; }}void Create_Head(BiTree *THead,BiTree T){ (*THead)->LTag = Link; (*THead)->Lchild = T; (*THead)->RTag = Thread; while(T->Rchild->Rchild) T = T->Rchild; T->Rchild->Rchild = (*THead); T->Rchild->RTag = Thread; (*THead)->Rchild = T;}int main(){ BiTree T,THead; printf("请前序遍历输入树\n"); THead = (BiTree) malloc(sizeof(BiTNode)); Create_Bitree(&T); pre = THead; In_Threading(T); Create_Head(&THead,T); printf("后序输出树\n"); In_Order_Traverse(THead); printf("\n"); return 0;}
1 0
- 数据结构学习:利用链表建立二叉树
- 数据结构之二叉树建立
- 数据结构-二叉树的建立
- 数据结构--二叉树--按给定的先序序列建立二叉链表(二叉树的存储)
- 建立二叉树的二叉链表
- 【数据结构学习】二叉树
- 数据结构学习 链表的建立
- 数据结构_树_二叉树的建立、遍历、复制与移除_二叉链表存储_C++实现
- python数据结构--二叉树建立与遍历
- 数据结构 二叉树的建立与遍历
- 数据结构之二叉树(遍历、建立、深度)
- 数据结构之二叉树(遍历、建立、深度)
- 数据结构之二叉树(遍历、建立、深度)
- 数据结构之二叉树(遍历、建立、深度)
- 数据结构之二叉树(遍历、建立、深度)
- 数据结构之二叉树(遍历、建立、深度)
- 数据结构----二叉树----建立与遍历
- 数据结构之 平衡二叉树的建立
- 笔记
- 黑马程序员-java基础-IO流
- 【软考】-UML图
- 路径中 斜杠/和反斜杠\ 的区别
- Lecture3-1Learning with different data label
- 数据结构学习:利用链表建立二叉树
- IOS 网络开发框架
- 一维数组的内部存储方法
- Android 开源框架Universal-Image-Loader完全解析(一)--- 基本介绍及使用
- 第三周项目1 顺序表的基本运算(3)
- NSMutableString的用法和注意事项
- C语言指针数组与数组指针
- 第三周项目一 顺序表的基本运算(1)
- NSString 与 NSArray 的相互转换