数据结构之二叉树

来源:互联网 发布:港澳资讯点金手软件 编辑:程序博客网 时间:2024/06/05 21:15

二叉树:二叉树是每个节点最多有两个子树的树结构

二叉树分两种:顺序结构的二叉树和链式存储的二叉树

但前者容易造成空间的浪费,所以适合用于完全二叉树
而二叉树链表就不会出现这样的问题

一、二叉树链表结构: lchild-data-rchild
一个数据域和两个指针域,分别存放左孩子和右孩子的指针
这里写图片描述

二叉树链表C代码实现:

#include "string.h"#include "stdio.h"    #include "stdlib.h"   #include "io.h"  #include "math.h"  #include "time.h"#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0#define MAXSIZE 100 /* 存储空间初始分配量 *///二叉树分两种:顺序结构的二叉树和链式存储的二叉树//但前者容易造成空间的浪费,所以适合用于完全二叉树//而二叉树链表就不会出现这样的问题// 二叉树链表:  lchild-data-rchild//一个数据域和两个指针域,分别存放左孩子和右孩子的指针#define ClearBiTree DestroyBITree; typedef int Status ;int index = 1;typedef char String[24];   //在这里我们把0号单元存放字符串的长度String str;typedef char Ele;Ele Nil = ' ';            //Nil为空 //赋值字符数组Status StrAssign(String T,char *chars){    int i;    if(strlen(chars)>MAXSIZE){        return ERROR;    }else{        T[0] = strlen(chars);        for(i=1;i<=T[0];i++){            T[i] = *(chars+i-1);        }    }    return OK;}//定义二叉树链表的数据结构typedef struct BiTNode{    Ele data;                    //数据域     struct BiTNode *lchild,*rchild;  //两个指针域 }BiTNode,*BiTree; //初始化为空的空二叉树 Status InitBiTree(BiTree *T){    *T = NULL;    return OK; } //摧毁一个二叉树,递归实现void DestroyBiTree(BiTree *T){    if(*T){        if((*T)->lchild){            DestroyBiTree(&(*T)->lchild);    //销毁左孩子树         }        if((*T)->rchild){            DestroyBiTree(&(*T)->rchild);   //销毁右孩子树         }        free(*T);        *T = NULL;    }} //构造二叉树//这里我们使用  # 作为空的判断,并赋值为NULL //继续递归实现 void CreateBiTree(BiTree *T) {    Ele ch;    ch = str[index++];    if(ch=='#'){        *T = NULL;    } else{        *T = (BiTree)malloc(sizeof(BiTNode));  //分配结点        if(!*T){            return;   //如果分配失败,返回         }         (*T)->data = ch;  //赋值         CreateBiTree(&(*T)->lchild);//构造左结点         CreateBiTree(&(*T)->rchild);//构造右结点    }}//是否为空? Status BiTreeEmpty(BiTree T){    if(T){        printf("该二叉树不为空\n");        return FALSE;    }else{        printf("该二叉树为空\n");        return TRUE;    }} //返回二叉树的深度//递归的终止条件为0;//由于return 对于i和j进行+1操作,//所以实现了逐级递增 int BiTreeDepth(BiTree T){    int i,j;    if(!T){        return ERROR;    }    if(T->lchild){        i = BiTreeDepth(T->lchild);     }else{        i = 0;    }    if(T->rchild){        j = BiTreeDepth(T->rchild);    }else{        j = 0;    }    return i>j?i+1:j+1;} //返回二叉树的根Ele Root(BiTree T){    if(BiTreeEmpty(T)){        return Nil;    }else{        return T->data;    }}//三种遍历方式//前序void PreOrder(BiTree T){    if(T==NULL){        return;    }    printf("%c ",T->data);   /* 先结点,显示结点数据 */      //根-->左-->右     PreOrder(T->lchild);     //再左子树     PreOrder(T->rchild);     //右子树 }//中序void MiddleOrder(BiTree T){    if(T==NULL){        return ;    }    MiddleOrder(T->lchild);           //左-->根--->右     printf("%c ",T->data);    MiddleOrder(T->rchild);}//后序void PostOrder(BiTree T){    if(T==NULL){        return;    }    PostOrder(T->lchild);         //左-->右-->根     PostOrder(T->rchild);    printf("%c ",T->data); }int main(){    int i;    BiTree T;    Ele e;    InitBiTree(&T);     StrAssign(str,"ABDH#K###E##CFI###G#J##");    CreateBiTree(&T);    printf("树的深度=%d \n\n",BiTreeDepth(T));    printf("树的根=%c \n",Root(T));    //前序遍历    printf("前序遍历:");    PreOrder(T);    printf("\n");    //中序遍历    printf("中序遍历:");    MiddleOrder(T);    printf("\n");    //后序遍历     printf("后序遍历:");    PostOrder(T);    printf("\n\n");    //清空     printf("清空后\n");    DestroyBiTree(&T);     BiTreeEmpty(T);     return 0;}

这里写图片描述

二、二叉排序树

一般我们把小于结点p放在p结点的左边–p->lchild,将大于p结点的放在右边–p->rchild.

删除结点图:
1、
这里写图片描述

2、
这里写图片描述

#include "stdio.h"    #include "stdlib.h"   #include "io.h"  #include "math.h"  #include "time.h"#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0#define MAXSIZE 100 /* 存储空间初始分配量 */typedef int Status;//二叉树结构 typedef struct BiTNode{    int data;    struct BiTNode *lchild,*rchild;  }BiTNode,*BiTree;/* 递归查找二叉排序树T中是否存在key, *//* 指针f指向T的双亲,其初始调用值为NULL *//* 若查找成功,则指针p指向该数据元素结点,并返回TRUE *//* 否则指针p指向查找路径上访问的最后一个结点并返回FALSE */Status SearchBiTree(BiTree T,int key,BiTree f,BiTree *p){    if(!T){  //查找不成功         *p = f;        return FALSE;    }else if(key==T->data){   //查找成功         *p = T;        return TRUE;    }else if(key<T->data){        return SearchBiTree(T->lchild,key,T,p);    //继续左子树查找     }else {        return SearchBiTree(T->rchild,key,T,p);    //继续右子树找     }}//插入一个点(数据) Status InsertBiTree(BiTree *T,int key){    BiTree p,s;    if(!SearchBiTree(*T,key,NULL,&p)){        s = (BiTree)malloc(sizeof(BiTNode));   //新结点         s->data = key;        s->lchild = s->rchild = NULL;        if(!p){          //如果查找的二叉树刚好为空,则插入作为根结点             *T = s;        }else if(key<p->data){   //插入左边             p->lchild = s;        }else if(key>p->data){   //插入右边             p->rchild = s;        }        return TRUE;    //不是关键字,并且插入成功     }else{        return FALSE;  //说明是二叉树的关键字     }} //删除一个结点pStatus Delete(BiTree *p){    BiTree q,s;    if((*p)->rchild==NULL){   //右空,只需重接左结点         q = *p;        *p = (*p)->lchild;        free(q);    }else if((*p)->lchild==NULL){  //左空, 只需重接右结点        q =*p;        *p = (*p)->rchild;        free(q);    }else{                    //左右均不为空,那就需要重接左右结点         q = *p;        s = (*p)->lchild;     //先转左边,然后右到尽头,最终找到删除点的前驱,,         while(s->rchild){     //个人觉得这里的删除并不是唯一的,也可以先右再左 ,                               q = s;            //只要符合大小的排序就行            s = s->rchild;        }        (*p)->data = s->data;          if(q!=(*p)){            q->rchild = s->lchild;  /*  重接q的右子树 */         }else{            q->lchild = s->lchild;/*  重接q的左子树 */        }         free(s);    }    return TRUE;} //递归找到要删除的结点Status DeleteBiTree(BiTree *T,int key){    if(!T){        return FALSE;    }else if((*T)->data == key){        Delete(T);    }else if(key<(*T)->data){        return DeleteBiTree(&(*T)->lchild,key);    }else{        return DeleteBiTree(&(*T)->rchild,key);    }} //遍历 void PreOrderTraverse(BiTree T){     if(T==NULL)        return;    printf("%d ",T->data);/* 显示结点数据,可以更改为其它对结点操作 */    PreOrderTraverse(T->lchild); /* 再先序遍历左子树 */    PreOrderTraverse(T->rchild); /* 最后先序遍历右子树 */}int main(){    int arr[10] = {62,88,58,47,35,73,51,99,37,93};    BiTree T = NULL;    int i;    //此时将数组变成一颗排序二叉树比较简单    for(i=0;i<10;i++){        InsertBiTree(&T,arr[i]);    }     //当画出图后,我们用前序遍历的遍历出来的结果和输出的结果是一致的     PreOrderTraverse(T);    printf("\n");     DeleteBiTree(&T,47);    PreOrderTraverse(T);    printf("\n");    DeleteBiTree(&T,93);        PreOrderTraverse(T);    return 0;}

这里写图片描述

0 0
原创粉丝点击