二叉树的顺序存储结构
来源:互联网 发布:李白 知乎 编辑:程序博客网 时间:2024/05/16 09:21
#ifndef TREE_H
#define MAX_TREE_SIZE 20 /* 二叉树的最大结点数 */#define OK 1#define ERROR -1typedef int Status ;typedef char TElemType ;typedef TElemType SqBiTree[MAX_TREE_SIZE]; /* 0号单元存储根结点 */ typedef struct { int level,order; /* 结点的层,本层序号(按满二叉树计算) */ }position; /////////////////基本操作////////////////////////////Status InitBiTree(SqBiTree T);void DestroyBiTree();Status CreateBiTree(SqBiTree T);Status BiTreeEmpty(SqBiTree T);int BiTreeDepth(SqBiTree T);Status Root(SqBiTree T,TElemType *e);TElemType Value(SqBiTree T,position e);Status Assign(SqBiTree T,position e,TElemType value);TElemType Parent(SqBiTree T,TElemType e);TElemType LeftChild(SqBiTree T,TElemType e);TElemType RightChild(SqBiTree T,TElemType e);TElemType LeftSibling(SqBiTree T,TElemType e);TElemType RightSibling(SqBiTree T,TElemType e);void Move(SqBiTree Q,int j,SqBiTree T,int i);Status InsertChild(SqBiTree T,TElemType p,Status LR,SqBiTree c);Status DeleteChild(SqBiTree T,position p,int LR);void PreTraverse(SqBiTree T,int e);Status PreOrderTraverse(SqBiTree T,Status(*Visit)(TElemType));void InTraverse(SqBiTree T,int e);Status InOrderTraverse(SqBiTree T,Status(*Visit)(TElemType));void PostTraverse(SqBiTree T,int e);Status PostOrderTraverse(SqBiTree T,Status(*Visit)(TElemType));void LevelOrderTraverse(SqBiTree T,Status(*Visit)(TElemType));void Print(SqBiTree T);#endif
#include<stdio.h>#include<stdlib.h>#include<math.h>#include<string.h>#include "c6_1.h"Status InitBiTree(SqBiTree T){/*构造空二叉树T,因为T是固定数组,不会改变,故不需要&*/int i ;for(i=0;i<MAX_TREE_SIZE;i++)T[i]=NULL;return OK;}void DestoryBiTree(SqBiTree T){/*由于SqBiTree 是定长的,无法销毁*/}Status CreateBiTree(SqBiTree T){/*按层次次输入二叉树中结点的值,(字符型),构造顺序存储结构的二叉树T*/int i =0;int l;char s[MAX_TREE_SIZE];printf("请按层次输入二叉树节点的值(字符),空格表示空结点,结点数<%d:\n",MAX_TREE_SIZE);gets(s); /*输入字符串*/l = strlen(s);/*求字符串的长度*/for(;i<l;i++){/*将字符串赋值给T*/T[i]=s[i];if(i!=0&&T[(i+1)/2-1]==NULL&&T[i]!=NULL){printf("出现无双亲的非根结点%c\n",T[i]);exit(ERROR);}}for(i=l;l<MAX_TREE_SIZE;l++)/*将空值赋给l以后的值*/T[i]=NULL;return OK ;}#define ClearBiTree InitBiTree /* 在顺序存储结构中,两函数完全一样 */Status BiTreeEmpty(SqBiTree T){/* 初始条件: 二叉树T存在 */ /* 操作结果: 若T为空二叉树,则返回TRUE,否则FALSE */if(T[0]==NULL)return true;elsereturn false;}int BiTreeDepth(SqBiTree T){ /* 初始条件: 二叉树T存在。操作结果: 返回T的深度 */ int i,j=-1; for(i=MAX_TREE_SIZE-1;i>=0;i--) /* 找到最后一个结点 */ if(T[i]!=NULL) break; i++; /* 为了便于计算 */ do j++; while(i>=pow(2,j)); return j;}Status Root(SqBiTree T,TElemType *e){ /* 初始条件: 二叉树T存在 */ /* 操作结果: 当T不空,用e返回T的根,返回OK;否则返回ERROR,e无定义 */if(BiTreeEmpty(T))return ERROR;else{*e=T[0];return OK ;}}TElemType Value(SqBiTree T,position e){ /* 初始条件: 二叉树T存在,e是T中某个结点(的位置) */ /* 操作结果: 返回处于位置e(层,本层序号)的结点的值 */return T[(int)pow(2,e.level-1)+e.order-2];}Status Assign(SqBiTree T,position e,TElemType value){ /* 初始条件: 二叉树T存在,e是T中某个结点(的位置) */ /* 操作结果: 给处于位置e(层,本层序号)的结点赋新值value */int i = (int)pow(2,e.level-1)+e.order-2;/*计算出要插入的位置*//*插入检查*/if(value!=NULL&&T[int((i+1)/2)-1]==NULL){printf("值不为空,但没有双亲结点\n");return ERROR;}else if(value==NULL&&T[2*i+1]!=NULL&&T[2*i+2]!=NULL){printf("双亲不为空,但孩子都不为空\n");return ERROR;}T[i]= value;return OK ;}TElemType Parent(SqBiTree T,TElemType e){ /* 初始条件: 二叉树T存在,e是T中某个结点 */ /* 操作结果: 若e是T的非根结点,则返回它的双亲,否则返回"空" */int i;if(T[0]==NULL)/*空树*/return ERROR ;for(i=0;i<MAX_TREE_SIZE;i++){if(T[i]==e)return T[(int)(i+1)/2-1];}return NULL;}TElemType LeftChild(SqBiTree T,TElemType e){/*初始条件:二叉树T存在,e是T中的结点*//*操作结果:返回e的左孩子*/int i ;if(T[0]==NULL)/*空树*/return ERROR;for(i=0;i<MAX_TREE_SIZE;i++){if(T[i]==e)return T[2*i+1];}return NULL;}TElemType RightChild(SqBiTree T,TElemType e){/*初始条件:二叉树T存在,e是T中的结点*//*操作结果:返回e的右孩子*/int i ;if(T[0]==NULL)/*空树*/return ERROR;for(i=0;i<MAX_TREE_SIZE;i++){if(T[i]==e)return T[2*i+2];}return NULL;}TElemType LeftSibling(SqBiTree T,TElemType e){ /* 初始条件: 二叉树T存在,e是T中某个结点 */ /* 操作结果: 返回e的左兄弟。若e是T的左孩子或无左兄弟,则返回"空" */int i;if(T[0]==NULL)return ERROR;for(i=0;i<MAX_TREE_SIZE;i++){if(T[i]==e&&i%2==0)/*找到e且其序号为偶数(是右孩子)*/return T[i-1];}return NULL;}TElemType RightSibling(SqBiTree T,TElemType e){/*初始条件:二叉树T存在,e是T中的某个结点*//*操作结果:返回e的右兄弟,若e是T的右孩子或是无右兄弟,则返回空*/int i ;if(T[0]==NULL)return NULL;for(i=0;i<MAX_TREE_SIZE;i++){if(T[i]==e&&i%2==1)/*找到e且其序号为偶数(是右孩子)*/return T[i+1];}return NULL;}void Move(SqBiTree Q,int j,SqBiTree T,int i){/* 把从Q的j结点开始的子树移为从T的i结点开始的子树 */if(Q[2*j+1]!=NULL) /*Q的左子树不为空*/Move(Q,(2*j+1),T,(2*i+1));if(Q[2*j+2]!=NULL) /*Q的右子树不空*/Move(Q,(2*j+2),T,(2*i+2));/*把Q的j结点的右子树移为T的i结点的右子树*/T[i]=Q[j];Q[j]=NULL;}Status InsertChild(SqBiTree T,TElemType p,Status LR,SqBiTree c){/* 初始条件: 二叉树T存在,p是T中某个结点的值,LR为0或1,非空二叉树c与T */ /* 不相交且右子树为空 */ /* 操作结果: 根据LR为0或1,插入c为T中p结点的左或右子树。p结点的原有左或 */ /* 右子树则成为c的右子树 */int i,k ;for(i=0;i<MAX_TREE_SIZE;i++){if(T[i]==p&&T[i]!=NULL)break;}k=2*i+1+LR;/*p的左孩子或是右孩子的位置*/if(T[k]!=NULL) /* p原来的左或右孩子不空 */Move(T,k,T,2*k+2); /* 把从T的k结点开始的子树移为从k结点的右子树开始的子树 */ Move(c,i,T,k); /* 把从c的i结点开始的子树移为从T的k结点开始的子树 */ return OK;}Status DeleteChild(SqBiTree T,position p,int LR){ /* 初始条件: 二叉树T存在,p指向T中某个结点,LR为1或0 */ /* 操作结果: 根据LR为1或0,删除T中p所指结点的左或右子树 */return OK;} Status(*VisitFunc)(TElemType); /* 函数变量 */ void PreTraverse(SqBiTree T,int e){ /* PreOrderTraverse()调用 */ VisitFunc(T[e]); if(T[2*e+1]!=NULL) /* 左子树不空 */ PreTraverse(T,2*e+1); if(T[2*e+2]!=NULL) /* 右子树不空 */ PreTraverse(T,2*e+2); } Status PreOrderTraverse(SqBiTree T,Status(*Visit)(TElemType)) { /* 初始条件: 二叉树存在,Visit是对结点操作的应用函数 */ /* 操作结果: 先序遍历T,对每个结点调用函数Visit一次且仅一次。 */ /* 一旦Visit()失败,则操作失败 */ VisitFunc=Visit; if(!BiTreeEmpty(T)) /* 树不空 */ PreTraverse(T,0); printf("\n"); return OK; } void InTraverse(SqBiTree T,int e) { /* InOrderTraverse()调用 */ if(T[2*e+1]!=NULL) /* 左子树不空 */ InTraverse(T,2*e+1); VisitFunc(T[e]); if(T[2*e+2]!=NULL) /* 右子树不空 */ InTraverse(T,2*e+2); } Status InOrderTraverse(SqBiTree T,Status(*Visit)(TElemType)) { /* 初始条件: 二叉树存在,Visit是对结点操作的应用函数 */ /* 操作结果: 中序遍历T,对每个结点调用函数Visit一次且仅一次。 */ /* 一旦Visit()失败,则操作失败 */ VisitFunc=Visit; if(!BiTreeEmpty(T)) /* 树不空 */ InTraverse(T,0); printf("\n"); return OK; } void PostTraverse(SqBiTree T,int e) { /* PostOrderTraverse()调用 */ if(T[2*e+1]!=NULL) /* 左子树不空 */ PostTraverse(T,2*e+1); if(T[2*e+2]!=NULL) /* 右子树不空 */ PostTraverse(T,2*e+2); VisitFunc(T[e]); } Status PostOrderTraverse(SqBiTree T,Status(*Visit)(TElemType)) { /* 初始条件: 二叉树T存在,Visit是对结点操作的应用函数 */ /* 操作结果: 后序遍历T,对每个结点调用函数Visit一次且仅一次。 */ /* 一旦Visit()失败,则操作失败 */ VisitFunc=Visit; if(!BiTreeEmpty(T)) /* 树不空 */ PostTraverse(T,0); printf("\n"); return OK; } void LevelOrderTraverse(SqBiTree T,Status(*Visit)(TElemType)) { /* 层序遍历二叉树 ,相当于遍历数组*/ int i=MAX_TREE_SIZE-1,j; while(T[i]==NULL) i--; /* 找到最后一个非空结点的序号 */ for(j=0;j<=i;j++) /* 从根结点起,按层序遍历二叉树 */ if(T[j]!=NULL) Visit(T[j]); /* 只遍历非空的结点 */ printf("\n"); }void Print(SqBiTree T){ /* 逐层、按本层序号输出二叉树 */ int j,k; position p; TElemType e; for(j=1;j<=BiTreeDepth(T);j++) { printf("第%d层: ",j); for(k=1;k<=pow(2,j-1);k++) { p.level=j; p.order=k; e=Value(T,p); if(e!=NULL) printf("%d:%c ",k,e); } printf("\n"); }} Status visit(TElemType e){ printf("%c ",e); return OK; }void main(){SqBiTree T;InitBiTree(T);//if(BiTreeEmpty(T)){//printf("树为空\n");//}CreateBiTree(T);//if(!BiTreeEmpty(T)){//printf("树不为空\n");//}//printf("%d\n",BiTreeDepth(T));//ClearBiTree(T);//if(BiTreeEmpty(T)){//printf("树为空\n");//}//TElemType e ;//Root(T,&e);//printf("根为: %c\n",e);//position p;//p.level=2;//p.order=1;//printf("%c\n",Value(T,p));//Assign(T,p, '7');//printf("%c\n",Value(T,p));printf("4 is parent = %c\n",Parent(T,'4'));printf("5 is leftchild=%c\n",LeftChild(T,'5'));printf("5 is RightChild=%c\n",RightChild(T,'5'));printf("5 is LeftSibling=%c\n",LeftSibling(T,'5'));printf("2 is RightSibling=%c\n",RightSibling(T,'2'));Print(T);printf("层序遍历二叉树:\n"); LevelOrderTraverse(T,visit); printf("中序遍历二叉树:\n"); InOrderTraverse(T,visit); printf("后序遍历二叉树:\n"); PostOrderTraverse(T,visit);}
总结:
用一组连续的存储单元依次自上而下,自左向右存储完全二叉树的节点元素。将完全二叉树中的第i个结点存储在一维数组中的第i-1的分量中。
对于二叉树的顺序存储结构适合存储完全二叉树,否则会浪费大量的存储空间,最坏的情况是,一个深度为k且只有k个结点的单支书需要2^k-1的一维数组。
主要参考:严蔚敏数据结构
http://www.cnblogs.com/cpoint/p/3479782.html,对此作者表示感谢,给我很大的帮助
0 0
- 二叉树的顺序存储结构
- 基于顺序存储的二叉树结构
- 二叉树的顺序存储结构
- 二叉树的顺序存储结构
- 二叉树的顺序存储结构
- 二叉树的顺序存储结构
- 【数据结构】二叉树的顺序存储结构--遍历二叉树
- 二叉树的顺序存储结构的C++实现
- (数据结构第六章)二叉树的顺序存储结构
- 二叉树的顺序存储
- 二叉树的顺序存储
- 二叉树的顺序存储
- 二叉树的顺序存储
- 二叉树的顺序存储
- 二叉树的顺序存储
- 二叉树的顺序存储
- 二叉树的顺序存储
- 第十一周项目1-二叉树构造算法的验证--由顺序存储结构转为二叉链存储结构
- IDA6.5 by dalao带arm和x86的f5
- 黑马程序员--Eclipse开发工具使用介绍
- 华为机试练习---求最小差值
- 华为机试练习---括号匹配问题
- 项目总结
- 二叉树的顺序存储结构
- 表视图默认选中第一个cell以及button外沿特性设置
- 生产者消费者问题(多进程+共享内存+信号量)
- 浅谈三层
- 华为机试---删除多行的重复数字
- JSP页面的动态包含和静态包含示例及介绍
- Add Two Numbers Leetcode
- [zoj 3802]Easy 2048 Again 状压DP
- 01背包问题