二叉树
二叉树代码
二叉树: //先序遍历 void PreOrder(BTNode *t) { if(!t) return; printf("%d ", t->element); PreOrder(t->lChild); PreOrder(t->rChild); } void PreOrderTree(BinaryTree *tree) { if(!tree) return; PreOrder(tree->root); } //求二叉树的高度 int Height(BTNode *t) { if(!t) return 0; int l=Height(t->lChild); int r=Height(t->rChild); if(l>r) return l+1; else return r+1; } //求二叉树中所有节点的数量 void CountNodes(BTNode *t,int *count) { if(!t) return; *count++; CountNodes(t->lChild, count); CountNodes(t->rChild, count); } int CountN(BinaryTree *tree) { if(!tree) return 0; int count=0; CountNodes(tree->root, &count); return count; } //求二叉树中的最大值 void MaxNode(BTNode *t,int *max) { if(!t) return; if(t->element > *max) *max=t->element; MaxNode(t->lChild, max); MaxNode(t->rChild, max); } int MaxTree(BinaryTree *tree) { if(!tree) return -1; int max=-1; MaxNode(tree->root, &max); return max; } //求二叉树中叶子节点的数量 void CountLeaf(BTNode *t,int *count) { if(!t) return; if(!t->lChild && !t->rChild) *count++; CountLeaf(t->lChild, count); CountLeaf(t->rChild, count); } int CountL(BinaryTree *tree) { if(!tree) return 0; int count=0; CountLeaf(tree->root, &count); return count; } //交换二叉树中每个节点的左右子树 void Exchange(BTNode *t) { BTNode *tmp; if(!t) return; tmp=t->lChild; t->lChild=t->rChild; t->rChild=tmp; Exchange(t->lChild); Exchange(t->rChild); } void ExchangeTree(BinaryTree *tree) { if(!tree) return; Exchange(tree->root); } //拷贝一颗二叉树,将q拷贝一份放到p中 void Copy(BTNode *p, BTNode *q) { if(!q) return; p=(BTNode *)malloc(sizeof(BTNode)); p->element=q->element; Copy(p->lChild, q->lChild); Copy(p->rChild, q->rChild); } void CopyTree(BinaryTree *oldtree, BinaryTree *newtree) { if(!oldtree) return; Copy(newtree->root, oldtree->root); } //按先序方法删除一颗二叉树 void Delete(BTNode *t) { BTNode *l,*r; if(!t) return; l=t->lChild; r=t->rChild; free(t); Delete(l); Delete(r); } // 宽度优先遍历 void BFS(BinaryTree *tree) { if(!tree || tree->root) return; Queue Q; //用于存储结点指针的队列 BTNode *p; EnQueue(Q, tree->root); while(!IsEmpty(Q)){ Front(Q, &p); DeQueue(Q); printf("%d ", p->element); if(p->lChild) EnQueue(Q, p->lChild); if(p->rChild) EnQueue(Q, p->rChild); } } //1 利用宽度优先遍历计算度为1的结点的数量 int BFS_Degree1(BinaryTree *tree) { if(!tree || tree->root) return 0; Queue Q; //用于存储结点指针的队列 BTNode *p; int count=0; EnQueue(Q, tree->root); while(!IsEmpty(Q)){ Front(Q, &p); DeQueue(Q); if((p->lChild && !p->rChild) || (!p->lChild && p->rChild)) count++; if(p->lChild) EnQueue(Q, p->lChild); if(p->rChild) EnQueue(Q, p->rChild); } return count; } //2 求二叉树中大于x的节点的数量 void LargeThanX(BTNode *t,int *count, int x) { if(!t) return; if(t->element > x) *count++; LargeThanX(t->lChild, count, x); LargeThanX(t->rChild, count, x); } int LTX(BinaryTree *tree, x) { if(!tree) return 0; int count=0; LargeThanX(tree->root, &count, x); return count; } // 求二叉树的平均值 void Avgerage(BTNode *t,int *total, int *count) { if(!t) return; *total=*total+t->element; *count++; Avgerage(t->lChild, total, count); Avgerage(t->rChild, total, count); } double AvgTree(BinaryTree *tree) { if(!tree) return 0; int count=0; int total=0; Average(tree->root, &total, &count); if(count!=0) return total/count; else return 0; } //求二叉树中比x大的最小数据 void MinLTX(BTNode *t,int *min, int x) { if(!t) return; if(t->element > x && t->element < *min) *min=t->element; MinLTX(t->lChild, min, x); MinLTX(t->rChild, min, x); } int MLTX(BinaryTree *tree, int x) { if(!tree) return -1; int min=99999999; MinLTX(tree->root, &min, x); return min; } //扩展:求二叉搜索树中的最小数据(要求算法时间复杂度不高于log2(n)) int MinBST(BSTree *tree) { BSTNode *p; if(!tree || tree->root) return -1; p=tree->root; while(p->lChild){ p=p->lChild; } return p->element; } //判断以p和q为根的二叉树是否相似 BOOL IsSimilar(BTNode *p, BTNode *q) { if(!p&&q || p&&!q) return FALSE: if(!p&&!q) return TRUE; return IsSimilar(p->lChild, q->lChild)&&IsSimilar(p->rChild, q->rChild); } //计算两棵二叉树的相似度(相似度是指具有相同位置的结点的数量 //与包含结点最多的二叉树的结点数量的比例) void CountSimilarNodes(BTNode *p, BTNode *q, int *count){ if(!p&&q || p&&!q) return : if(!p&&!q) return ; *count++; CountSimilarNodes(p->lChild, q->lChild, count); CountSimilarNodes(p->rChild, q->rChild, count); } void CountNodes(BTNode *t,int *count){ if(!t) return; *count++; CountNodes(t->lChild, count); CountNodes(t->rChild, count); } double Similarity(BinaryTree *tree1, BinaryTree *tree2){ if(!tree1||!tree2) return 0; int count1=0, count2=0,c=0; CountNodes(tree1->root, &count1); CountNodes(tree2->root, &count2); if(count1==0 && count2==0) return 1.0; CountSimilarNodes(tree1->root, tree2->root, &c); if(count1>count2) return c/count1; else return c/count2; } 设计一个算法求二叉树的内路径长度和外路径长度。 算法思想: ipath和outpath分别为二又树的内路径长度和外路径长度变量,h用于记录当前考察节点t的路径长度,初始传入时为0,1初始传入为树根节点,ipath 和epath初始均为0,递归程序如下: (1) 若t为空,则返回: (2)若t为叶子节点,则根据h计算t的外 路径长度,并加入outpath;否则,根据h计算t的内路径长度,并加入inpath: (3) 以t的左子树的根节点指针,inpath, outpath和h+1为参数,递归计算整个二叉树的内路径和外路径长度: (4) 以t的右子树的根节点指针,inpath,epath和h+1为参数,递归计算整个二叉树的内路径和外路径长度。 //level为当前深度 void PL(BTNode *t, int *inpath, int *outpath, int level) { if(!t) return;//边界条件 if(!t->lChild && !t->rChild)//叶子结点,计入外路径长度 *outpath = *outpath + level; else//非叶结点,计入内路径长度 *inpath = *inpath + level; PL(t->lChild, inpath, outpath, level+1);//递归计算左子树 PL(t->rChild, inpath, outpath, level+1);//递归计算右子树 } void GetPL(BinaryTree *tree) { int inpath=0, outpath=0; if(!tree || !tree->root) return ; //如果。。。。 PL(tree->root, &inpath, &outpath, 0); printf("内路径和外路径长度分别为%d和%d",inpath,outpath); } //求二叉树中第i层中的结点的数量 void LevelCount(BTNode *t, int i, int level, int *count) { if(!t) return; if(level==i) *count++; else if(level>i) return; else{ LevelCount(t->lChild, i, level+1, count); LevelCount(t->rChild, i, level+1, count); } } int LCT(BinaryTree *tree, int i) { if(!tree || !tree->root) return 0; int count=0; LevelCount(tree->root, i, 1, &count); return count; } //求二叉树中以元素值为x的节点为根的子树的高度 算法思想:1 采用递归遍历思想,查找值为x的节点p,找到则返回 2 计算以p为根的二叉树的高度,并返回 int Height(BTNode *t){ if(!t) return 0; int l=Height(t->lChild); int r=Height(t->rChild); if(l>r) return l+1; else return r+1; } int HeightX(BTNode *t, int x) { int m, n; if(!t) return 0; if(t->element==x) return Height(t); else{ m=HeightX(t->lChild, x); if(m>0) return m; n=HeightX(t->rChild, x); if(n>0) return n; } return 0; } void FindNode(BTNode *t, int x, BTNode **p){ if(!t) return; if(t->element == x){ *p=t; return; } FindNode(t->lChild, x, p); FindNode(t->rChild, x, p); } int HeightX(BianryTree *tree, int x){ if(!tree || !tree->root) return -1; //如果。。。。 BTNode *p=NULL; FindNode(tree->root, x, &p); if(!p) return 0; // return Height(p); } 补充题:求与值为x的节点在二叉树的同一层的节点的数量(包含值为x的节点) void LevelX(BTNode *t, int x,int *level, int h){ if(!t) return; if(t->element==x){ *level=h; return;} LevelX(t->lChild, x, level, h+1); LevelX(t->rChild, x, level, h+1); } void CountLevel(BTNode *t, int level, int *count, int h){ if(!t) return; if(level==h) *count++; else{ //说明else的原因 CountLevel(t->lChild, level,count, h+1); CountLevel(t->rChild, level,count, h+1); } } int CountLX(BinaryTree *tree, int x){ if(!tree || !tree->root) return -1; //如果。。。。 int count=0, level=0; LevelX(tree->root, x, &level, 1); if(level==0) return 0; // CountLevel(tree->root, level, &count, 1); return count; } //求二叉树的宽度 //计算高度 int Height(BTNode *t) { if(!t) return 0; int l=Height(t->lChild); int r=Height(t->rChild); if(l>r) return l+1; else return r+1; } //递归计算每层的宽度 void Weight(BTNode *t, int w[], int level) { if(!t) return; w[level]++;//该层宽度加一 Weight(t->lChild, w, level+1); Weight(t->rChild, w, level+1); } //基于递归的实现方法(深度优先) int WeightOfTree(BinaryTree *tree) { if(!tree) return 0; int i,max=-1, h = Height(tree-root); int *w=(int*)malloc(sizeof(int)*(h+1)); for(i=0;i<h+1;i++) w[i]=0; Weight(tree->root, w, 1); for(i=1;i<h+1;i++) if(w[i]>max) max=w[i]; return max; } //求指定结点p在给定二叉排序树中的层次 int level(BSTNode *t, BSTNode *p) { int count=0; BSTNode *q; if(!t) return -1; q=t; while(q){ count++; if(q->element==p->element) return count; else if(q->element>p->element) q=q->lChild; else q=q->rChild; } return -1; } //扩展:求二叉树中值为x的节点的层号 void LevelX(BTNode *t, int x,int *level, int h){ if(!t) return; if(t->element==x){ *level=h; return;} LevelX(t->lChild, x, level, h+1); LevelX(t->rChild, x, level, h+1); } //判定给定二叉树是否为二叉排序树 BOOL IsLarger(int x, BTNode *t){ if(!t) return TRUE; return x>t->element && IsLarger(x, t->lChild) && IsLarger(x, t->rChild); } BOOL IsSmaller(int x, BTNode *t){ if(!t) return TRUE; return x<t->element && IsSmaller(x, t->lChild) && IsSmaller(x, t->rChild); } BOOL IsBSTree(BTNode *t) { if(!t) TRUE; int temp=t->element; if(IsLarger(temp, t->lChild) && IsSmaller(temp, t->rChild)) return IsBSTree(t->lChild)&&IsBSTree(t->rChild); else return FALSE; } //判断一棵二叉树是否是满二叉树 int Height(BTNode *t){ if(!t) return 0; int l=Height(t->lChild); int r=Height(t->rChild); if(l>r) return l+1; else return r+1; } void CountNodes(BTNode *t,int *count){ if(!t) return; *count++; CountNodes(t->lChild, count); CountNodes(t->rChild, count); } BOOL IsFullTree(BinaryTree *tree){ if(!tree->root) return TRUE; int h=Height(tree->root); int total=0; CountNodes(tree->root, &total); int x=1, i; for(i=0;i<h;i++) x=x*2; x=x-1; if(x==total) return TRUE; else return FALSE; } //判断一棵二叉树是否是完全二叉树 int Height(BTNode *t){ if(!t) return 0; int l=Height(t->lChild); int r=Height(t->rChild); if(l>r) return l+1; else return r+1; } void mapping(BTNode *t, BTNode *arr[], int i){ if(!t) return; arr[i]=t; mapping(t->lChild, arr, 2*i+1); mapping(t->rChild, arr, 2*i+2); } BOOL IsCompleteTree(BinaryTree *tree){ int h=Height(tree->root); //h表示。。。。。。 int max=1, i; //max表示。。。。。。 for(i=0;i<h;i++) max=max*2; max=max-1; BTNode **arr=(BTNode**)malloc(sizeof(BTNode*)*max); for(i=0;i<x;i++) arr[i]=NULL; //初始化 mapping(tree->root, arr, 0); for(i=0;i<max;i++) if(arr[i]==NULL) break; if(i==max) return TRUE; //当i==max时,当前二叉树为满二叉树,则也是完全二叉树 for(;i<max;i++) if(arr[i]!=NULL) return FALSE: return TRUE; } //试计算二叉树的加权路径长度 void WPL(BTNode *t, int *wpl, int level) { if(!t) return; if(!t->lChild && !t->rChild) *wpl = *wpl + t->element*level; WPL(t->lChild, wpl, level+1); WPL(t->rChild, wpl, level+1); } int GetWPL(BinaryTree *tree) { if(!tree || !tree->root) return -1; //如果。。。。 int wpl=0; WPL(tree->root, &wpl, 0); return wpl; } //利用宽度优先遍历判断完全二叉树 BOOL IsCompleteTree(BinaryTree *tree) { if(!tree->root) return TRUE; Queue Q; //用于存储结点指针的队列 BTNode *p; BOOL flag=FALSE; //是否已发生空指针出队的标记,FALSE表示未发生 EnQueue(Q, tree->root); while(!IsEmpty(Q)){ Front(Q, &p); DeQueue(Q); if(!flag && !p) flag=TRUE; //当出队元素第一次为空时,设置flag=TRUE else if(flag && p)//已有空指针出队的情况下,发现非空结点,则不是完全二叉树 return FALSE; else if(!flag && p){ //未有空指针出队的情况下,非空结点出队,此时将该结点 EnQueue(Q,p->lChild); //的左右孩子(不论是否为空)依次进队 EnQueue(Q,p->rChild); } else if(flag && !p) //已有空指针出队,且当前出队元素为空指针,则继续循环 continue; } return TRUE; } //设计一个尽可能快的算法,求出在一颗二叉排序树中关键字大于k的节点数量 int CountGK(BSTNode *bt,int k) { if(!bt) return 0; return Count(bt->root,k); } int Count(BSTNode *t,ink) { if(t==NULL) return 0; if(t->data<=k) //当前节点的关键字小于等于k时,左子树不必满足条件,无需遍历 return Count(t->rchild); else//当前节点的关键字大于k时,左右子树都要考虑 return 1+Count(t->lchild)+Count(t->rchild); } //判断一个二叉搜索树是否是AVL树 int Height(BTNode *t){ if(!t) return 0; int l=Height(t->lChild); int r=Height(t->rChild); if(l>r) return l+1; else return r+1; } BOOL IsAVL(BTNode *t) { if(!t) return TRUE; int l=Height(t->lChild); //计算左子树的高度 int r=Height(t->rCHild); //计算右子树的高度 if(l-r>1 || l-r<-1) //判断当前结点是否符合AVL树的定义 return FALSE; else return IsAVL(t->lChild)&&IsAVL(t->rChild); } BOOL IsAVLTree(BinaryTree *tree) { return IsAVL(tree->root); } //判断一棵二叉树是否是二叉搜索树 BOOL IsLarge(BTNode *t, int x) //判断x是否大于t中的所有结点 { if(!t) return TRUE; return x>t->element && IsLarge(t->lChild, x) && IsLarge(t->rChild, x); } BOOL IsSmall(BTNode *t, int x) //判断x是否小于t中的所有结点 { if(!t) return TRUE; return x<t->element && IsSmall(t->lChild, x) && IsSmall(t->rChild, x); } BOOL IsBST(BTNode *t) { if(!t) return TRUE; BOOL flag = IsLarge(t->lChild, t->element) && IsSmall(t->rChild, t->element); return flag && IsBST(t->lChild) && IsBST(t->rChild); } //判断二叉树中节点p和q的祖先后裔关系 BOOL IsInTree(BTNode *t, BTNode *p) { if(!t) return FALSE; return t==p || IsInTree(t->lChild, p) || IsInTree(t->rChild, p); } void IsAncestor(BTNode *p, BTNode *q) { if(IsInTree(p, q)) printf("p is a ancestor of q!"); else if(IsInTree(q, p)) printf("q is a ancestor of p!"); } //判断二叉树中节点p和q的兄弟关系 void IsSibiling(BTNode *t, BTNode *p, BTNode *q, int *flag) { if(!t) return ; if((t->lChild==p && t->rChild==q)||(t->lChild==q && t->rChild==p)) *flag=1; IsSibiling(t->lChild, p, q); IsSibiling(t->rChild, p, q); } BOOL Brothers(BinaryTree *tree, BTNode *p, BTNode *q) { int flag=0; if(!tree||!tree->root) return FALSE; IsSibiling(tree->root, p, q, &flag); if(flag) return TRUE; else return FALSE; } //判断A和B之间是否有祖先后裔关系 void Find(BTNode *t, BTNode **node, int x) { if(!t) return; if(t->element==x){ *node=t; return; } Find(t->lChild, node, x); Find(t->rChild, node, x); } void Level(BTNode *t, int x, int *le, int t_level) //返回x所在层的层号 { if(!t) return; if(t->element == x){ *le=t_level; return;} Level(t->lChild, x, le,t_level+1); Level(t->rChild, x, le,t_level+1); } BOOL JudgeAncestor(BinaryTree *tree, int A, int B) { BTNode *p==NULL, *q=NULL; int A_level=-1, B_level=-1; Level(tree->root, A, &A_level, 1); Level(tree->root, B, &B_level, 1); if(A_level==-1 || B_level==-1) { printf("不存在祖先后裔关系\n");return FALSE;} if(A_level<B_level){ Find(tree->root, &p, A); Find(p, &q, B); if(!q) {printf("不存在祖先后裔关系\n"); return FALSE}; else {printf("A是B的祖先\n");return TRUE;} } else{ Find(tree->root, &p, B); Find(p, &q, A); if(!q) { printf("不存在祖先后裔关系\n");return FALSE; } else { printf("B是A的祖先\n"); return TRUE; } } } //p和q分别为二叉树中任意两个结点,试编写算法查找找到p和q的最近公共祖先结点 BOOL IsAncestor(BTNode *t, BTNode *p, Stack *S)//判断t是否是x的祖先,若是则将t进栈 { if(!t) return FALSE; if(t==p || IsAncestor(t->lChild, p, S) || IsAncestor(t->rChild, p, S)){ Push(S, t); return TRUE; } return FALSE; } BTNode *FindNA(BTNode *t, BTNode *p, BTNode *q) { Stack S1, S2; if(!IsAncestor(t, p, S1)) {printf("p节点不存在"); return NULL}; if(!IsAncestor(t, q, S2)) {printf("q节点不存在"); return NULL}; BTNode *tp=NULL; while(Top(S1)==Top(S2)){ tp=Top(S1); Pop(S1); Pop(S2); } return tp; } //已知A和B具有祖先后裔关系,求A和B之间的距离(即A和B之间的路径长度) void Level(BTNode *t, int A, int B, int *la, int *lb, int t_level) { if(!t) return; if(t->element == A) *la=t_level; if(t->element == B) *lb=t_level; if(*la != -1 && *lb != -1) //用于在完成A和B的层号计算的前提下,提前退出递归 return; //该判断语句块可以不要 Level(t->lChild, x, le,t_level+1); Level(t->rChild, x, le,t_level+1); } int Distance(BinaryTree *tree, int A, int B) { if(!tree) return -1; int A_level=-1, B_level=-1; Level(tree->root, A, B, &A_level, &B_level, 1); if(A_level==-1 || B_level==-1) return -1; if(A_level>B_level) return A_level-B_level; else return B_level-A_level; } //求A和B的最近共同祖先 BOOL IsInTree(BTNode *t, int x) //判断x是否在t树中 { if(!t) return FALSE; if(t->element == x) return TRUE; return IsInTree(t->lChild, x) || IsInTree(t->rChild, x); } void FindAllAncestors(BTNode *t, int t_level, int x, BTNode *arr[]) { ////将x的祖先结点从上到下依次存储到数组中 if(!t) return; if(IsInTree(t, x)){ arr[t_level]=t; FindAllAncestors(t->lChild, t_level+1, x, arr); FindAllAncestors(t->rChild, t_level+1, x, arr); } else return; } int Height(BTNode *t){ if(!t) return 0; int l=Height(t->lChild); int r=Height(t->rChild); if(l>r) return l+1; else return r+1; } BTNode *GetNearestAncestor(BinaryTree *tree, int A, int B) { int h=Height(tree->root); int i; BTNode **arrA=(BTNode**)malloc(sizeof(BTNode*)*h); BTNode **arrB=(BTNode**)malloc(sizeof(BTNode*)*h); for(i=0;i<h;i++) arrA[i]=arrB[i]=NULL; FindAllAncestors(tree->root, 0, A, &arrA); //将A的祖先结点从上到下依次存储到数组中 FindAllAncestors(tree->root, 0, B, &arrB); //将B的祖先结点从上到下依次存储到数组中 for(i=h-1;i>=0;i--) //从后向前寻找相同且不为空的结点,该结点即为最近的共同祖先 if(arrA[i]==arrB[i] && arrA[i]!=NULL) return arrA[i]; }