数据结构之二叉树
来源:互联网 发布:港澳资讯点金手软件 编辑:程序博客网 时间: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
- 数据结构之二叉树
- 数据结构之二叉树
- 数据结构之二叉树
- 数据结构之二叉树
- 数据结构之二叉树
- 数据结构之二叉树
- 数据结构之二叉树
- 数据结构之二叉树
- 数据结构之二叉树
- 数据结构之二叉树
- 数据结构之二叉树
- 数据结构之二叉树
- 数据结构之二叉树
- 数据结构之二叉树
- 数据结构之二叉树
- 数据结构之二叉树
- 数据结构之二叉树
- 数据结构之二叉树
- C++11 并发指南五(std::condition_variable 详解)
- Spark加载放在Tomcat容器中的mlib模型报错:org.apache.hadoop.fs.ChecksumException
- HDU5873
- 日均数十亿请求!京东评价系统海量数据存储高可用设计
- python中字符串内部换行
- 数据结构之二叉树
- Java学习提要——String类对正则的支持
- spring boot 学习--07---配置文件处理
- 计算机视觉系列教程 (二)卷积与滤波详解
- chrome浏览器默认浏览方式变成了“移动端”的浏览方式,怎么恢复pc端浏览?
- jetbrains 所有产品的历史版本下载
- asp.net web api http put delete , iis 返回400.0 找不到错误的解决办法.
- NDK和JNI的使用
- Qt中条件编译或者叫编译开关