数据结构学习:利用链表建立二叉树

来源:互联网 发布: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
原创粉丝点击