二叉树的顺序存储结构
2014-09-02 21:23
495 查看
#ifndef TREE_H
#define MAX_TREE_SIZE 20 /* 二叉树的最大结点数 */ #define OK 1 #define ERROR -1 typedef 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; else return 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的一维数组。
主要参考:严蔚敏数据结构
/article/5137388.html,对此作者表示感谢,给我很大的帮助
相关文章推荐
- 二叉树的顺序存储结构
- 7-11 将二叉树的顺序存储结构转换成二叉链存储结构
- 二叉树的顺序存储结构
- 6-1-二叉树顺序存储结构-树和二叉树-第6章-《数据结构》课本源码-严蔚敏吴伟民版
- 数据结构与算法简记:根据层次顺序存储结构构建二叉树
- (数据结构第六章)二叉树的顺序存储结构
- ※数据结构※→☆非线性结构(tree)☆============二叉树 顺序存储结构(tree binary sequence)(十九)
- 【数据结构】二叉树的顺序存储结构--遍历二叉树
- ※数据结构※→☆非线性结构(tree)☆============二叉树 顺序存储结构(tree binary sequence)(十九)
- 大话数据结构十四:二叉树的顺序存储结构(数组实现)
- 数据结构与算法简记:根据层次顺序存储结构构建二叉树---改进版
- 二叉树的顺序存储结构
- 顺序存储结构的二叉树
- 二叉树的顺序存储结构的C++实现
- 二叉树的顺序存储结构
- C语言 二叉树顺序存储结构的先序遍历算法
- java由先根中根遍历序列建立二叉树,由标明空子树建立二叉树,有完全二叉树顺序存储结构建立二叉链式存储结构
- 心动C++情牵二叉树
- Java之美[从菜鸟到高手演变]之数据结构基础之树、二叉树
- 第14周、项目2—二叉树排序树中查找的路径