[数据结构]顺序二叉树的实现

来源:互联网 发布:查看内存软件 编辑:程序博客网 时间:2024/06/11 14:45

顺序二叉树的数据结构为:

#define MAX_TREE_SIZE 100;

typedef TElemType Btree[MAX_TREE_SIZE ];

Btree bt;

顺序二叉树是用一组地址连续的存储单元依次自上而下自左至右存储完全二叉树上的结点元素,即将完全二叉树上编号为i的结点元素存储在如上定义的一维数组中下标为i-1的分量中。顺序二叉树仅适用于完全二叉树,因为在最坏的情况下,一个深度为k且只有k个结点的单枝树(不存在度为2的结点)却需要长度为2^k-1的一维数组。


#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#define MAXLENGTH 100#define ClearBiTree InitTree typedef char TElemType;//二叉树存储类型typedef int QElemType;//队列存储类型typedef TElemType Btree[MAXLENGTH];//二叉树顺序存储结构,下表0为根节点typedef struct {QElemType *base;int front;int rear;}Queue;//队列存储结构typedef struct{int level;//节点的层int order;//本层序号(按满二叉树算)}position;//记录节点的位置TElemType NIL = ' ';int(*VisitFunc)(TElemType); // 函数变量 //初始化二叉树,构造空二叉树void InitTree(Btree t){int i;for(i=0;i<MAXLENGTH;i++){t[i] = NIL;}}//销毁二叉树void DestroyTree(){//因为Btree为丁长类型,无法销毁}void CreateBtree(Btree t){int i;int len;char s[MAXLENGTH];printf("请按层输入结点值,空格表示空节点,结点数<%d\n",MAXLENGTH);gets(s);//将输入赋给slen = strlen(s); //输入字符串的长度//将s的值赋给二叉树for(i=0;i<len;i++){t[i] = s[i];//当结点不是根节点及结点的双亲结点为NIL及当前结点不为NIL,则无双亲if(i !=0 && t[(i+1)/2-1] == NIL && t[i] != NIL){printf("出现无双亲的非根结点");exit(0);}}for(i = len;i<MAXLENGTH;i++){t[i] = NIL;}}//判断二叉树是否为空,1为空,0不空int IsTreeEmpty(Btree t){if(t[0] == NIL)return 1;return 0;}//得到树的深度int getTreeDepth(Btree t){int i=0;int j =-1;//找到最后一个结点,并记录结点的数据for(i = MAXLENGTH-1;i>=0;i--){if(t[i] != NIL)break;}i++;do{j++;}while(i>=pow(2,j));//pow(2,depth-1)<=i<pow(2,depth)return j;}//返回二叉树的根int getTreeRoot(Btree t,TElemType *e){//二叉树为空if(IsTreeEmpty(t)){return 0;}else{*e = t[0];return 1;}}//返回处于某层的值TElemType getVal(Btree t,position p){//将层和层中某结点的序号转换为数组下标,pow(2,p.level-1)为level之前的所有结点数,p.order-1为当前层的位置return t[(int)pow(2,p.level-1)-1+p.order-1];}//给处于某层的结点赋予新值int assign(Btree t,position p,TElemType e){int i = (int)pow(2,p.level-1)+p.order-2;//叶子非空而双亲为空if(e != NIL && t[(i+1)/2-1] == NIL){return 0;}else if(e == NIL && t[i*2+1] != NIL || t[i*2+2] != NIL){return 0;}t[i] = e;return 1;}//返回任意非根结点的双亲TElemType getParent(Btree t,TElemType e){int i ;if(t[0] == NIL){return NIL;}for(i = 1;i < MAXLENGTH; i++){if(t[i] == e){return t[(i+1)/2-1];}}return NIL;}//返回左孩子TElemType getLeftChild(Btree t,TElemType e){if(t[0] == NIL)return NIL;for(int i =0;i<MAXLENGTH;i++){if(t[i] == e){return t[2*i+1];}}return NIL;}//返回右孩子TElemType getRightChild(Btree t,TElemType e){if(t[0] == NIL)return NIL;for(int i=0;i<MAXLENGTH;i++){if(t[i] == e)return t[2*i+2];}return NIL;}//返回左兄弟结点TElemType getLeftSibling(Btree t,TElemType e){if(t[0] == NIL)return NIL;for(int i=0;i<MAXLENGTH;i++){if(t[i] ==e && i%2 ==0)return t[i-1];}return NIL;}//返回右兄弟结点TElemType getRightSibling(Btree t,TElemType e){if(t[0] == NIL)return NIL;for(int i=0;i<MAXLENGTH;i++){if(t[i] ==e && i%2 !=0)return t[i+1];}return NIL;}//把从某一二叉树中的某一结点移动到二叉树中另外一结点的子树void MoveTo(Btree m1,int i1,Btree m2,int i2){//左子树不空if(m1[2*i1+1] != NIL)MoveTo(m1,2*i1+1,m2,2*i2+1);if(m1[2*i1+2] != NIL)MoveTo(m1,2*i1+2,m2,2*i2+2);m2[i2] = m1[i1];m1[i1] = NIL;}//根据LR判定插入结点c,使其成为双亲结点的左或右子树,而原来的左或右子树为c的右边子树void InsertChild(Btree t,TElemType e,int LR,Btree c){int pos;int i =0;for(pos =0;pos<(int)pow(2,getTreeDepth(t)-1);pos++){if(t[pos] == e)break;}int k = 2*pos+1+LR;//当LR为0为左子树,当LR为1为右子树,k为序号if(t[k] != NIL)//e原来左或右孩子不空{MoveTo(t,k,t,2*k+2); // 把从T的k结点开始的子树移为从k结点的右子树开始的子树 }MoveTo(c,i,t,k); // 把从c的i结点开始的子树移为从T的k结点开始的子树 }// 构造一个空队列Qint InitQueue(Queue *Q){(*Q).base=(QElemType *)malloc(MAXLENGTH*sizeof(QElemType));//分配定长的空间,相当于一个数组if(!(*Q).base) // 存储分配失败 exit(0);(*Q).front=(*Q).rear=0;//初始化下标return 1;}// 插入元素e为Q的新的队尾元素 int EnQueue(Queue *Q,QElemType e){if((*Q).rear>=MAXLENGTH){ // 队列满,增加1个存储单元 (*Q).base=(QElemType *)realloc((*Q).base,((*Q).rear+1)*sizeof(QElemType));if(!(*Q).base) // 增加单元失败 return 0;}*((*Q).base+(*Q).rear)=e;(*Q).rear++;return 1;}// 若队列不空,则删除Q的队头元素,用e返回其值,并返回1,否则返回0 int DeQueue(Queue *Q,QElemType *e){if((*Q).front==(*Q).rear) // 队列空 return 0;*e=(*Q).base[(*Q).front];(*Q).front=(*Q).front+1;return 1;}// 根据LR为1或0,删除T中p所指结点的左或右子树 int DeleteChild(Btree T,position p,int LR){int i;int k=1; // 队列不空的标志 Queue q;InitQueue(&q); // 初始化队列,用于存放待删除的结点 i=(int)pow(2,p.level-1)+p.order-2; // 将层、本层序号转为矩阵的序号 if(T[i]==NIL) // 此结点空 return 0;i=i*2+1+LR; // 待删除子树的根结点在矩阵中的序号 while(k){if(T[2*i+1]!=NIL) // 左结点不空 EnQueue(&q,2*i+1); // 入队左结点的序号 if(T[2*i+2]!=NIL) // 右结点不空 EnQueue(&q,2*i+2); // 入队右结点的序号 T[i]=NIL; // 删除此结点 k=DeQueue(&q,&i); // 队列不空 }return 1;}void PreTraverse(Btree T,int e){ // PreOrderTraverse()调用 VisitFunc(T[e]);//先调用函数VisitFunc处理根if(T[2*e+1]!=NIL) // 左子树不空 PreTraverse(T,2*e+1);//然后处理左子树if(T[2*e+2]!=NIL) // 右子树不空 PreTraverse(T,2*e+2);}// 先序遍历T,对每个结点调用函数Visit一次且仅一次。int PreOrderTraverse(Btree T,int(*Visit)(TElemType)){VisitFunc=Visit;if(!IsTreeEmpty(T)) // 树不空 PreTraverse(T,0);printf("\n");return 1;}// InOrderTraverse()调用void InTraverse(Btree T,int e){ if(T[2*e+1]!=NIL) // 左子树不空 InTraverse(T,2*e+1);VisitFunc(T[e]);if(T[2*e+2]!=NIL) // 右子树不空 InTraverse(T,2*e+2);}// 中序遍历T,对每个结点调用函数Visit一次且仅一次。int InOrderTraverse(Btree T,int(*Visit)(TElemType)){ VisitFunc=Visit;if(!IsTreeEmpty(T)) // 树不空 InTraverse(T,0);printf("\n");return 1;}// PostOrderTraverse()调用void PostTraverse(Btree T,int e){ if(T[2*e+1]!=NIL) // 左子树不空 PostTraverse(T,2*e+1);if(T[2*e+2]!=NIL) // 右子树不空 PostTraverse(T,2*e+2);VisitFunc(T[e]);}// 后序遍历T,对每个结点调用函数Visit一次且仅一次。 int PostOrderTraverse(Btree T,int(*Visit)(TElemType)){VisitFunc = Visit;if(!IsTreeEmpty(T)) // 树不空 PostTraverse(T,0);printf("\n");return 1;}// 层序遍历二叉树void LevelOrderTraverse(Btree T,int(*Visit)(TElemType)){int i=MAXLENGTH-1,j;while(T[i] == NIL)i--; // 找到最后一个非空结点的序号 for(j=0;j<=i;j++)  // 从根结点起,按层序遍历二叉树 if(T[j] != NIL)Visit(T[j]); // 只遍历非空的结点 printf("\n");}// 逐层、按本层序号输出二叉树void Print(Btree T){int j,k;position p;TElemType e;for(j=1;j<=getTreeDepth(T);j++){printf("第%d层: ",j);for(k=1; k <= pow(2,j-1);k++){p.level=j;p.order=k;e=getVal(T,p);if(e!=NIL)printf("%d:%c ",k,e);}printf("\n");}}int visit(TElemType e){printf("%c ",e);return 0;}int main(){int i,j;position p;TElemType e;Btree T,s;InitTree(T);CreateBtree(T);printf("建立二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n",IsTreeEmpty(T),getTreeDepth(T));i=getTreeRoot(T,&e);if(i)printf("二叉树的根为:%c\n",e);elseprintf("树空,无根\n");printf("层序遍历二叉树:\n");LevelOrderTraverse(T,visit);printf("中序遍历二叉树:\n");InOrderTraverse(T,visit);printf("后序遍历二叉树:\n");PostOrderTraverse(T,visit);printf("请输入待修改结点的层号 本层序号: ");scanf("%d%d%*c",&p.level,&p.order);e=getVal(T,p);printf("待修改结点的原值为%c请输入新值: ",e);scanf("%c%*c",&e);assign(T,p,e);printf("先序遍历二叉树:\n");PreOrderTraverse(T,visit);printf("结点%c的双亲为%c,左右孩子分别为",e,getParent(T,e));printf("%c,%c,左右兄弟分别为",getLeftChild(T,e),getRightChild(T,e));printf("%c,%c\n",getLeftSibling(T,e),getRightSibling(T,e));InitTree(s);printf("建立右子树为空的树s:\n");CreateBtree(s);printf("树s插到树T中,请输入树T中树s的双亲结点 s为左(0)或右(1)子树: ");scanf("%c%d%*c",&e,&j);InsertChild(T,e,j,s);Print(T);printf("删除子树,请输入待删除子树根结点的层号 本层序号 左(0)或右(1)子树: ");scanf("%d%d%d%*c",&p.level,&p.order,&j);DeleteChild(T,p,j);Print(T);ClearBiTree(T);printf("清除二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n",IsTreeEmpty(T),getTreeDepth(T));i=getTreeRoot(T,&e);if(i)printf("二叉树的根为:%c\n",e);elseprintf("树空,无根\n");system("pause");return 0;}


原创粉丝点击