二叉树的顺序存储结构

来源:互联网 发布:李白 知乎 编辑:程序博客网 时间: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
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孩子8个月发烧38怎么办 8个宝宝发烧38度怎么办 怀孕八个月不想要怎么办 怀孕八个月不想要了怎么办 八个月宝宝拉肚子拉水怎么办 八个月的宝宝拉肚子怎么办 八个月发烧38度怎么办 孩子特别调皮好动该怎么办 孩子有好动症该怎么办 在幼儿园好动的孩子该怎么办 18个月宝宝上火怎么办 打孩子越打上瘾怎么办 八个月不想要了怎么办 胎儿心脏畸形肺动脉瓣闭锁怎么办 小孩爱动怎么办补什么 初中孩子下午上课总犯困怎么办 孩子上课精神不集中怎么办 孩子玩兴奋了就打人怎么办 婴儿兴奋白天不睡觉怎么办 小孩读书精神不集中怎么办 小孩上课精神不集中怎么办 小孩学习精神不集中怎么办 孩子暑假天天看电视不出门怎么办 七个月宝宝缺铁怎么办 天天运动为什么还便秘怎么办 小孩学习注意力不集中怎么办 8个月宝贝太好动怎么办 学生在校受伤家长该怎么办 多动症小孩爱动手指怎么办 孩子大了不听话该怎么办 流产后吹了风怎么办 怀孕1周内喝酒了怎么办 怀孕6周喝酒了怎么办 怀孕后喝了酒怎么办 不知道怀孕喝酒了怎么办 不知道怀孕了喝酒了怎么办 怀孕5天喝酒了怎么办 打孩子耳光后脸肿了怎么办 老师说上课不专心怎么办 孩子不专心好动马虎怎么办 学生上课不认真听讲怎么办