非线性表-BiTree(二叉树)
作者:互联网
1.Status InitBiTree(BiTree *T) 构造空二叉树 2.Status DestroyBiTree(BiTree *T) 销毁二叉树,前提T存在 3.Status CreateBiTree(BiTree *T) 用先序遍历创建二叉树 4.Status ClearBiTree(BiTree *T) 清空二叉树,前提T存在5.int BiTreeDepth(BiTree T) 返回二叉树的深度,前提T存在 6.BiTree Root(BiTree T) 返回二叉树的根,前提T存在 7.ElemType Value(BiTree T,BiTree e) 返回e的值,前提T存在 8.Status Assign(BiTree T,BiTree *e,ElemType value) 结点e赋值为value,前提T存在 9.BiTree Parent(BiTree T,BiTree e) 若e是T中某个非根结点,则返回它的双亲,否则返回NULL,前提T存在 10.BiTree LeftChild(BiTree T,BiTree e) 返回e的左孩子。若e无左孩子,则返回NULL,前提T存在 11.BiTree RightChild(BiTree T,BiTree e) 返回e的右孩子。若e无右孩子,则返回NULL,前提T存在 12.BiTree LeftSibling(BiTree T,BiTree e) 返回e的左兄弟。若e是其双亲的左孩子或无左兄弟,则返回NULL,前提T存在 13.BiTree RightSibling(BiTree T,BiTree e) 返回e的右兄弟。若e是其双亲的右孩子或无右兄弟,则返回NULL,前提T存在 14.Status InsertChild(BiTree T,BiTree p,int LR,BiTree c) 初始条件:T存在,p指向T中某个结点,LR为0或1,非空二叉树c与T不相交且右子树为空。 操作结果:根据LR为0或1,插入c为T中p所指结点的左或右子树。p所指结点的原有左或右子树则成为c的右子树。
15.Status DeleteChild(BiTree T,BiTree p,int LR) 初始条件:T存在,p指向T中某个结点,LR为0或1
操作结果:根据LR为0或1,删除T中p所指结点的左或右子树
16.Status PreOrderTraverse(BiTree T) 先序遍历二叉树,前提T存在 17.Status InOrderTraverse(BiTree T) 中序遍历二叉树,前提T存在 18.Status PostOrderTraverse(BiTree T) 后序遍历二叉树,前提T存在 19.Status LevelOrderTraverse(BiTree T) 层序遍历二叉树,前提T存在
#include <stdio.h> #include <stdlib.h> //函数结果状态代码 #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #define OVERFLOW -1 typedef int elemType; typedef int status; typedef struct bitNode { elemType data; struct bitNode *lchild; struct bitNode *rchild; }bitNode,*bitTree,*BiTree;
1.Status InitBiTree(BiTree *T) 构造空二叉树
status initBitTree(bitTree *t) { (*t)=(bitTree)malloc(sizeof(bitNode)); if(!(*t))exit(OVERFLOW); (*t)->lchild=NULL; (*t)->rchild=NULL; return OK; }
2.Status DestroyBiTree(BiTree *T) 销毁二叉树,前提T存在
status DestroyBiTree(bitTree *T) { if(!(*T)) return OK; DestroyBiTree(&((*T)->lchild)); DestroyBiTree(&((*T)->rchild)); free(*T); return OK; }
3.Status CreateBiTree(BiTree *T) 用先序遍历创建二叉树
status CreateBiTree(bitTree *T) { char ch=getchar();//读入一个字符 if(ch=='.') //个人认为用.表示空树比较好(这样输入多个空树的时候方便检验有没有输入错误,但是如果用空格的话,嗯......实在是无法检验) *T=NULL; else { *T=(bitTree)malloc(sizeof(bitNode)); if(!(*T)) exit(OVERFLOW); (*T)->data=ch; CreateBiTree(&((*T)->lchild)); CreateBiTree(&((*T)->rchild)); } return OK; }
4.Status ClearBiTree(BiTree *T) 清空二叉树,前提T存在
status ClearBiTree(bitTree *T)//清空之后,根结点是改变了的 { if(!(*T)) return ERROR; DestroyBiTree(&((*T)->lchild)); DestroyBiTree(&((*T)->rchild));//这里的确是销毁,你没看错 free(*T); (*T)=(bitTree)malloc(sizeof(bitNode));//重新分配空间 if(!(*T)) exit(OVERFLOW); (*T)->lchild=NULL; (*T)->rchild=NULL; return OK; }
5.int BiTreeDepth(BiTree T) 返回二叉树的深度,前提T存在
int max(int a,int b) { return (a>=b)?a:b; }
int BiTreeDepth(bitTree T) { if(!T) return 0; else return max(BiTreeDepth(T->lchild),BiTreeDepth(T->rchild))+1; //这有个缺点,空树会返回深度1 }
6.BiTree Root(BiTree T) 返回二叉树的根,前提T存在
bitTree Root(bitTree T) { return T; }
7.ElemType Value(BiTree T,BiTree e) 返回e的值,前提T存在
//辅助函数 T若为空返回,否则若等于要找得数返回真,或者有孩子节点等于要找得数返回真,且t为e status Search(bitTree T,bitTree e) { if(!T) return FALSE; if(T==e||Search(T->lchild,e)==TRUE||Search(T->rchild,e)==TRUE) return TRUE; else return FALSE; }
elemType Value(bitTree T,bitTree e) { if(Search(T,e)==TRUE) return e->data; else return 0; }
8.Status Assign(BiTree T,BiTree *e,ElemType value) 结点e赋值为value,前提T存在
status Assign(bitTree T,bitTree *e,elemType value) { if(Search(T,*e)==TRUE) { (*e)->data=value; return OK; } return ERROR; }
9.BiTree Parent(BiTree T,BiTree e) 若e是T中某个非根结点,则返回它的父节点,否则返回NULL,前提T存在
bitTree Parent(bitTree T,bitTree e) { if(T==e)//没有双亲 return NULL; if(T->lchild==e||T->rchild==e)//根节点是双亲 return T; else if(Search(T->lchild,e)==TRUE)//根节点的左子树有要找得数 执行完search t指向e这个值的双亲,t->lchild指向e return Parent(T->lchild,e);//返回父母节点 else if(Search(T->rchild,e)==TRUE)//根节点的右子树有要找得数t指向e这个值的双亲,t->lchild指向e return Parent(T->rchild,e);//返回父母节点 else return NULL; }
//root指向根节点,p,q指向二叉树任意两个节点的指针,找到p,q公共祖先节点r; //向前追溯p的根节点pp,从pp出发寻找q节点,若找到则pp=r //向前追溯pp的根节点ppp,从ppp出发寻找q节点,若找到则pp=r void searchParent(bitTree root,bitTree p,bitTree q,bitTree r) { if(!root||!p||!q)return 0; bitTree pp; pp=p; while(pp!=NULL) { //以pp为根节点,第一次以p为根节点,在子树找q,找到说明pp是公共祖先节点 if(Search(pp,q)==TRUE){ r=pp; break; } pp=Parent(root,pp);//在树中找到pp的双亲,返回双亲节点 } }
10.BiTree LeftChild(BiTree T,BiTree e) 返回e的左孩子。若e无左孩子,则返回NULL,前提T存在
bitTree leftChild(bitTree T,bitTree e) { if(search(T,e)==TRUE) { return e->lchild; }else return NULL; }
11.BiTree RightChild(BiTree T,BiTree e) 返回e的右孩子。若e无右孩子,则返回NULL,前提T存在
bitTree rightChild(bitTree T,bitTree e) { if(search(T,e)==TRUE) { return e->rchild; }else return NULL; }
12.BiTree LeftSibling(BiTree T,BiTree e) 返回e的左兄弟。若e是其双亲的左孩子或无左兄弟,则返回NULL,前提T存在
bitTree leftSibling(bitTree t,bitTree e) { /** 先找到这个e的位置t */ if(Search(t,e)==TRUE&&Parent(t,e)->lchild!=e) return Parent(t,e)->lchild; else return NULL; }
13.BiTree RightSibling(BiTree T,BiTree e) 返回e的右兄弟。若e是其双亲的右孩子或无右兄弟,则返回NULL,前提T存在
bitTree rightSibling(bitTree t,bitTree e) { if(search(t,e)==TRUE&&Parent(t,e)->rchild!=e) return Parent(t,e)->rchild; else return NULL; }
14.Status InsertChild(BiTree T,BiTree p,int LR,BiTree c)
初始条件:T存在,p指向T中某个结点,LR为0或1,非空二叉树c与T不相交且右子树为空。
操作结果:根据LR为0或1,插入c为T中p所指结点的左或右子树。p所指结点的原有左或右子树则成为c的右子树。
status insertChild(bitTree t,bitTree p,int lr,bitTree c) { if(!t||Search(t,p)==FALSE) { return ERROR; } bitTree q; if(lr==0)//插入到p左边 { q=p->lchild; p->lchild=c; c->rchild=q; } /** o p o c o q */ else if(lr==1)//插入到p右边 { q=p->rchild; p->rchild=c; c->rchild=1; } else return ERROR; return OK; }
15.Status DeleteChild(BiTree T,BiTree p,int LR)
初始条件:T存在,p指向T中某个结点,LR为0或1
操作结果:根据LR为0或1,删除T中p所指结点的左或右子树
status deleteChile(bitTree t,bitTree p,int lr) { if(t&&Search(t,p)==FALSE) { return ERROR; } if(lr==0) { DestroyBiTree(&p->lchild); p->lchild=NULL; } else if(lr==1) { DestroyBiTree(&p->rchild); p->rchild=NULL; } else return ERROR; return OK; }
16.Status PreOrderTraverse(BiTree T) 先序遍历二叉树,前提T存在
1:递归
status PreOrderTraverse(bitTree T) { if(!T) return ERROR; printf("%c ",T->data); PreOrderTraverse(T->lchild); PreOrderTraverse(T->rchild); return OK; }
2:非递归
1 2 3 4 5 6 7 遍历顺序:1 2 4 5 3 6 7
步骤:
1:初始化栈 2:如果根节点不为空,入栈 3; 定义二叉树空节点topNode,存放弹出的栈顶元素 4:弹出的栈顶元素1,存topNode,访问该元素,若存在右节点先将右节点入栈3,然后左节点入栈2 5:弹出的栈顶元素2,存topNode,访问该元素,若存在右节点先将右节点入栈5,然后左节点入栈4 5:弹出的栈顶元素4,存topNode,访问该元素,没有左右节点 6:弹出的栈顶元素5,存topNode,访问该元素,没有左右节点 7:弹出的栈顶元素3,存topNode,访问该元素,若存在右节点先将右节点入栈7,然后左节点入栈6 5:弹出的栈顶元素6,存topNode,访问该元素,没有左右节点 5:弹出的栈顶元素7,存topNode,访问该元素,没有左右节点:
//数据元素为二叉树的栈,用于非递归二叉树树的遍历 typedef struct stackNode { bitTree bnode; struct stackNode *next; }Stack; int initStack(Stack &stack) { stack= (Stack *) malloc(sizeof(Stack)); if (!stack)return 0; //内存分配失败,存储空间不够 return 1; } //入栈 stack指向栈顶 Stack *push(Stack *top,bitTree t) { Stack *p=(Stack *)malloc(sizeof(Stack)); p->bnode=t; p->next=top; top=p; return top; } //出栈 stack指向栈顶 Stack *pop(Stack *top,bitTree *t) { if(top) { Stack *s=top; top=top->next; printf("弹栈元素:%d ",s->bnode->data); if (top) { printf("栈顶元素:%d\n",s->bnode->data); }else{ printf("栈已空\n"); } t=s->bnode; free(s); } else { printf("栈内没有元素"); return top; } return top; }
void PreNormal(BitTree *parent) { Stack stack; if(initStack(stack)==0) { return ; } if(parent==NUll) { return ; } push(stack,*parent); BitTree topNode; while(pop(stack,topNode))//取栈顶元素,访问并出栈 { visit(topNode);//访问栈顶元素 if(topNode.right!=NULL)//存在右结点,则先将右结点入栈。因为左结点先遍历 { push(stack,*(topNode.right)); } if(topNode.left!=NULL) //存在左结点,左结点入栈 { push(stack,*(topNode.right)); } } }
17.Status InOrderTraverse(BiTree T) 中序遍历二叉树,前提T存在
1:递归
status InOrderTraverse(bitTree T) { if(!T) return ERROR; InOrderTraverse(T->lchild); printf("%c ",T->data); InOrderTraverse(T->rchild); return OK; }
2:非递归
概述:先将根结点入栈,然后根据根结点一直寻找到该左子树的最左边结点,访问该结点。如果该结点不存在右子树,直接将该结点出栈,
并一直出栈到栈顶的结点存在右子树。此时将栈顶结点出栈,并将该结点的右孩子结点入栈,并寻找到该结点右子树的最左边结点。 1 2 3 4 5 6 7 步骤: 1: 初始化栈 2:如果根节点不为空,入栈 3; 定义二叉树空节点topNode,存放弹出的栈顶元素 4: 取栈顶元素 存topNode 若该元素存在左节点,左节点入栈,topNode指向该元素,直到左节点元素为空1 2 4 5:取栈顶元素4 不存在右节点,直接出栈 出栈元素存入topNode,输出topNode ,继续取栈顶元素重复操作,直到存在右节点; 6:取栈顶元素2 存在右节点 ,直接出栈 出栈元素存入topNode,输出topNode ,存入右节点5 4: 取栈顶元素5 存topNode 若该元素存在左节点,左节点入栈,topNode指向该元素,直到左节点元素为空 5:取栈顶元素5 不存在右节点,直接出栈 出栈元素存入topNode,输出topNode ,继续取栈顶元素重复操作,直到存在右节点; 6:取栈顶元素1 存在右节点 ,直接出栈 出栈元素存入topNode,输出topNode ,存入右节点3 4: 取栈顶元素3 存topNode 若该元素存在左节点,左节点入栈,topNode指向该元素,直到左节点元素为空3 6 5:取栈顶元素6 不存在右节点,直接出栈 出栈元素存入topNode,输出topNode ,继续取栈顶元素重复操作,直到存在右节点; 6:取栈顶元素3 存在右节点 ,直接出栈 出栈元素存入topNode,输出topNode ,存入右节点7 4: 取栈顶元素7 存topNode 若该元素存在左节点,左节点入栈,topNode指向该元素,直到左节点元素为空 5:取栈顶元素7 不存在右节点,直接出栈 出栈元素存入topNode,输出topNode ,继续取栈顶元素重复操作,直到存在右节点;
void MidNormal(BitTree *parent) { Stack stack; if(initStack(stack)==0) { return ; } if(parent==NUll) { return ; } push(stack,*parent); BitTree topNode; while(top(stack,topNode))//取栈顶节点 { /* * 首先,一直遍历到最左边的结点 */ while (topNode.left != NULL) { //左孩子结点不为空,入栈 push(stack, *(topNode.left));//左孩子结点入栈 topNode = *(topNode.left);//看下一个左孩子结点 } /* * 其次,判断其是否存在右孩子结点。 * 不存在右孩子结点,直接将该结点出栈 */ int flag = 1; while (flag && topNode.right == NULL) { pop(stack, topNode);//出栈 visit(topNode); flag = top(stack, topNode);//取栈顶结点,继续判断 } /* * 存在右孩子结点,当前结点出栈,并将右孩子结点入栈 */ if (pop(stack, topNode)) { visit(topNode); push(stack, *(topNode.right)); } } }
18.Status PostOrderTraverse(BiTree T) 后序遍历二叉树,前提T存在
1:递归
status PostOrderTraverse(bitTree T) { if(!T) return ERROR; PostOrderTraverse(T->lchild); PostOrderTraverse(T->rchild); printf("%c ",T->data); return OK; }
2:非递归
/* 1 * 2 3 * 4 5 6 7 *逆后续:1 3 7 6 2 5 4 *遍历存入栈中 入栈顺序 1 2 3 6 7 4 5 出栈 1 3 7 6 2 5 4 *后续: 4 5 2 6 7 3 1 弹出的顺序为后序遍历 */ void PostNormal(BitTree *parent) { /* * 声明两个栈,遍历树的管理栈和备用栈 */ Stack stack,newstack; if(initStack(stack)==0) { return; } if(initStack(newstack)==0) { return; } if(parent==NULL) { return; } push(stack,*parent); bitTree topNode;//记录当前栈顶结点 while(pop(stack,topNode)) { push(newstack,*topNode);//入栈 if(topNode.lchild!=NULL) { push(stack,*(topNode.lchild)); } if(topNode.rchild!=NULL) { push(stack,*(topNode.lchild)); } } while(pop(newstack,topNode)) { printf("%d",*(topNode)); } }
19.Status LevelOrderTraverse(BiTree T) 层序遍历二叉树,前提T存在
//数据元素为二叉树的队列,用于层次遍历 typedef struct QueNode { bitTree Quedata; struct QueNode *next; }QueNode,*QueuePtr; typedef struct { QueuePtr front; QueuePtr rear; }LinkQueue; //构造空队列 status InitQue(LinkQueue *q) { (*q).front=(QueuePtr)malloc((sizeof(QueNode))); if(!(*q).front) exit(-1); (*q).front->next=NULL; (*q).rear=(*q).front; return OK; } //判队列空 status QueEmpty(LinkQueue q) { if(q.front==q.rear)return TRUE; else return FALSE; } //插入元素e作为新的队列元素,前提是q存在 status EnQue(LinkQueue *q,bitTree e) { QueuePtr p=(QueuePtr)malloc((sizeof(QueNode))); if(!p)exit(OVERFLOW); p->Quedata=e; p->next=NULL; (*q).rear->next=p; (*q).rear=p; return OK; } //若队列不空,删除队头元素,用e返回其值 status DeQue(LinkQueue *q,bitTree *e) { if((*q).front==(*q).rear)return ERROR; QueuePtr p=(*q).front->next; *e=p->Quedata; (*q).front->next=p->next; if((*q).rear==p) { (*q).rear=(*q).front; } free(p); return OK; }
status levelTraverse(bitTree t) { if(!t) { return ERROR; } LinkQueue q; InitQue(&q); bitTree p; EnQue(&q,t);//头结点入队 while(QueEmpty(q)==FALSE) { DeQue(&q,&p); printf("%c",p->data); if(p->lchild) { EnQue(&q,p->lchild); } if(p->rchild) { EnQue(&q,p->rchild); } } return OK; }
结束:
int main() { bitTree T,c; char ch; printf("测试第一个基本操作\n"); if(InitBiTree(&T)==OK&&InitBiTree(&c)==OK)printf("二叉树初始化成功!\n"); printf("第三个基本操作\n"); printf("先序遍历构造二叉树T\n"); CreateBiTree(&T); ch=getchar();//吸收换行符 printf("先序遍历:\n"); PreOrderTraverse(T); printf("中序遍历:\n"); InOrderTraverse(T); printf("后序遍历:\n"); PostOrderTraverse(T); printf("层序遍历:\n"); LevelOrderTraverse(T); printf("构造二叉树c\n"); CreateBiTree(&c); printf("层序遍历:"); LevelOrderTraverse(c); printf("第七个基本操作\n"); printf("T的深度为:%d\n",BiTreeDepth(T));
printf("测试第八、九个操作\n"); printf("根为:%c\n",Value(T,Root(T)));
printf("第十至第十四个基本操作\n"); bitTree m=T->lchild->lchild,n=T->rchild;//这里我是在知道二叉树结构的情况下进行赋值的 printf("m为:%c,n为:%c\n",Value(T,m),Value(T,n)); printf("m的双亲为:%c,n的双亲为:%c\n",Value(T,Parent(T,m)),Value(T,Parent(T,n))); printf("m的左孩子为:%c,n的左孩子为:%c\n",Value(T,leftChild(T,m)),Value(T,leftChild(T,n))); printf("m的右孩子为:%c,n的右孩子为:%c\n",Value(T,rightChild(T,m)),Value(T,rightChild(T,n))); printf("m的左兄弟为:%c,n的左兄弟为:%c\n",Value(T,leftSibling(T,m)),Value(T,leftSibling(T,n))); printf("m的右兄弟为:%c,n的右兄弟为:%c\n",Value(T,rightSibling(T,m)),Value(T,rightSibling(T,n)));
printf("第十个基本操作\n"); printf("将n的值改为G\n"); Assign(T,&n,'G'); printf("层序遍历:"); LevelOrderTraverse(T);
printf("第十四个基本操作\n"); InsertChild(T,n,0,c); printf("层序遍历T:"); LevelOrderTraverse(T);
printf("第十五个基本操作\n"); DeleteChild(T,n,0); printf("层序遍历T:"); LevelOrderTraverse(T);
printf("第二个基本操作\n"); if(DestroyBiTree(&T)==OK) printf("销毁二叉树T成功!\n"); return 0; }
标签:结点,return,BiTree,非线性,二叉树,bitTree,节点,topNode 来源: https://www.cnblogs.com/Y-flower/p/15506868.html