typedef struct BiTNOde{ ElemType data; //数据域 struct BiTNode *lchild,*rchild; //左、右孩子指针 }BiTNode,*BiTree; //先序遍历(PreOrder) void PreOrder(BiTree T){ if(T!=NULL){ visit(T); PreOrder(T->lchild); PreOrder(T->rchild); } } //中序遍历(InOrder) void InOrder(BiTree T){ if(T!=NULL){ InOrder(T->lchild); visit(T); InOrder(T->rchild); } } //后序遍历(PostOrder) void PostOrder(BiTree T){ if(T!=NULL){ PostOrder(T->lchild); PostOrder(T->rchild); visit(T); } } //先序遍历的非递归算法1 void PreOrder2_1(BiTree T){ InitStack(S); BiTree p=T; while(p || !IsEmpty(S)){ if(p){ visit(p); Push(S,p); p=p->lchild; } else{ Pop(S,p); p=p->rchild; } } } //先序遍历的非递归算法2 void PreOrder2_2(BiTree T){ InitStack(S); BiTree p=T; Push(S,p); while(!IsEmpty(S)){ Pop(S,p); visit(p); if(p->rchild) Push(S,p->rchild); if(p->lchild) Push(S,p->lchild); } } //中序遍历的非递归算法 void InOrder2(BiTree T){ InitStack(S); BiTree p=T; while(p || !IsEmpty(S)){ if(p){ Push(S,p); p=p->lchild; } else{ Pop(S,p); visit(p); p=p->rchild; } } } //后序遍历的非递归算法 void PostOrder2(BiTree T){ InitStack(S); BiTree rp=NULL,p=T; //rp指示最近访问过的结点 while(p || IsEmpty(S)){ while(p){ Push(S,p); p=p->lchild; } GetTop(S,p); if(p->rchild && p->rchild!=rp) p=p->rchild; else{ Pop(S,rp); visit(rp); p=NULL; } } } //二叉树的层次遍历 void LevelOrder(BiTree T){ InitQueue(Q); BiTree p; EnQueue(Q,T); while(!IsEmpty(Q)){ DeQueue(Q,p); visit(p); if(p->lchild!=NULL) EnQueue(Q,p->lchild); if(p->rchild!=NULL) EnQueue(Q,p->rchild); } } //由中序+先序、中序+后序生成一棵二叉树:见我的其他文章。 //线索二叉树的存储结构: typedef struct ThreadNode{ ElemType data; struct ThreadNode *lchild,*rchild; int ltag,rtag; }ThreadNode,*ThreadTree; //通过中序遍历对二叉树线索化的递归算法: void InThread(ThreadTree &p,ThreadTree &pre){ if(p!=NULL){ InThread(p->lchild,pre); if(p->lchild==NULL){ p->lchild=pre; p->ltag=1; } if(pre!=NULL && pre->rchild==NULL){ //建立前驱结点的后继线索 pre->rchild=p; pre->rtag=1; } pre=p; //标记当前结点成为刚刚访问过的结点 InThread(p->rchild,pre); } } //通过中序遍历建立中序线索二叉树的主过程: void CreateInThread(ThreadTree T){ ThreadTree pre=NULL; if(T!=NULL){ InThread(T,pre); pre->rchild=NULL; //处理遍历的最后一个结点 pre->rtag=1; } } /*线索二叉树的遍历*/ //求中序线索二叉树中中序序列下的第一个结点: ThreadNode *FirstNode(ThreadNode *p){ while(p->ltag==0) p=p->lchild; //最左下结点(不一定是叶结点) return p; } //求中序线索二叉树中结点p在中序序列下的后继结点: ThreadNode *NextNode(ThreadNode *p){ if(p->rtag==0) return FirstNode(p->rchild); else return p->rchild; //rtag==1直接返回后继线索 } //利用上面两个算法,可以写出不含头结点的中序线索二叉树的中序遍历的算法: void InOrder3(ThreadNode *T){ for(ThreadNode *p=FirstNode(T);p!=NULL;p=NextNode(p)) visit(p); } //在中序线索二叉树中查找指定结点在二叉树后序遍历中的前驱结点 //算法思想:在后序序列中,若结点p有右子女,则右子女是其前驱,若元右子女而有左子女,则左子女是其前驱。 //若结点p左、右子女均元,设其中序左线索指向某祖先结点f(p是f右子树中按中序遍历的第一个结点为), //若f有左子女,则其左子女是结点p在后序下的前驱;若f元左子女,则顺其前驱找双亲的双亲,一直找到双亲有 //左子女,(这时左子女是p的前驱)。还有一种情况,若p是中序遍历的第一个结点,结点p在中序和后序下均元前驱。 ThreadTree InPostPre(ThreadTree T,ThreadTree p){ ThreadTree q; if(!p->rtag) q=p->rchild; //有右子女 else if(!p->ltag) q=p->lchild; //只有左子女 else if(!p->lchild) q=NULL; //p是中序遍历的第一个结点,无后序前驱 else{ while(p->ltag && p->lchild) p=p->lchild; if(!p->ltag) q=p->lchild; else q=NULL; //仅有单支树(p是叶子),已到根结点,p无后序前驱 } return q; } //打印从根到数据域为x的结点的路径 typedef struct { BiTree t; int tag; //tag=0表示左子女被访问,tag=1表示右子女被访问 } stack; void Search(BiTree T,ElemType x){ stack S[MaxSize]; top=-1; while(T || top>-1){ while(T && T->data!=x){ S[++top].t=T; S[top].tag=0; T=T->lchild; } if(T->data==x){ printf("打印从根到数据域为x的结点的路径:\n"); for(i=0;i<=top;i++) printf("%d ",s[i].t->data); exit(1); } while(top!=-1 && S[top].tag==1) top--; if(top!=-1){ S[top].tag=1; T=S[top].t->rchild; } } } //打印从m到n的路径 //递归算法 int b=0; //标记 void PrintTrace1(BiTree T,BiTree m,BiTree n){ if(T){ if(T==n){ b=1; print(T); return ; } PrintTrace(T->lchild); if(b==0) //若从左路径找到n,返回时不执行此处 PrintTrace(T->rchild); if(b==1){ print(T); //输出m到n的路径,是逆序的 if(T==m) exit(0); } } } //非递归算法 void PrintTrace2(BiTree T,BiTree m,BiTree n){ InitStack(S); p=T; r=NULL; while(p || !IsEmpty(S)){ if(p){ Push(S,p); p=p->lchild; } else{ GetTop(S,p); if(p->rchild && p->rchild!=r){ p=p->rchild; Push(S,p); p=p->lchild; } else{ Pop(S,p); if(p==n){ while(p && p!=m){ //输出m到n的路径,是逆序的 print(p); Pop(S,p); } print(p); //打印m return ; } r=p; //记录最近访问过的结点 p=NULL; } } } } //求二叉树的高度 //非递归算法 int BiTreeDepth1(BiTree T){ //采用层次遍历的非递归方法求解二叉树的高度 if(!T) return 0; int front=-1,rear=-1; int last=0,level=0; //last指向下一层第一个结点的位置 BiTree Q[MaxSize]; Q[++rear]=T; BiTree p; while(front<rear){ p=Q[++front]; if(p->lchild) Q[++rear]=p->lchild; if(p->rchild) Q[++rear]=p->rchild; if(front==last){ level++; last=rear; } } } //递归算法 int BiTreeDepth2(BiTree T){ if(!T) return 0; ldep=BiTreeDepth2(T->lchild); rdep=BiTreeDepth2(T->rchild); if(ldep>rdep) return ldep+1; else return rdep+1; } //求二叉树的宽度(即具有结点数最多的那一层的结点个数) int BiTreeWidth(BiTree T){ BiTree Q[MaxSize]; front=rear=-1; if(T) Q[++rear]=T; last=rear; count=0;max=0; while(front<rear){ p=Q[++front]; count++; if(p->lchild) Q[++rear]=p->lchild; if(p->rchild)Q[++rear]=p->rchild; if(front==last){ max=max>count?max:count; last=rear; count=0; } } return max; } //判断是否为完全二叉树 int IsCompleteBiTree(BiTree t){ InitQueue(Q); if(!T) return 1; EnQueue(Q,T); while(!IsEmpty(Q)){ DeQueue(Q,p); if(p){ EnQueue(Q,p->lchild); EnQueue(Q,p->rchild); } } else while(!IsEmpty(Q)){ DeQueue(Q,p); if(p) return 0; } } return 1; } //判断是否为满二叉树 void IsFullBiTree(BiTree T){ if(!T) return 1; BiTree Q[MaxSize]; front=-1;rear=-1; last=0; k=1;t=0; //k为每层最大数,t为计数 Q[++rear]=T; last=rear; while(front<rear){ p=Q[++front]; t++; if(p->lchild) Q[++rear]=p->lchild; if(p->rchild) Q[++rear]=p->rchild; if(front==last){ if(t!=k) return 0; t=0; k=2*k; last=rear; } } return 1; } //删除以数据域为x的结点(至多一个)为根的子树 //非递归算法 void Search1(BiTree T,ElemType x){ //层序遍历,找到相应结点煌父结点 BiTree Q[MaxSize]; if(T){ if(T->data==x){ DeleteXTree1(T); exit(0); } InitQueue(Q); EnQueue(Q,T); while(!IsEmpty(Q)){ DeQueue(Q,p); if(p->lchild) if(p->lchild->data==x){ DeleteXTree1(p->lchild); p->lchild=NULL; return ; } else EnQueue(Q,p->lchild); if(p->rchild) if(p->rchild->data==x){ DeleteXTree1(p->rchild); p->rchild=NULL; return ; } else EnQueue(Q,p->rchild); } } } void DeleteXTree1(BiTree T){ if(T){ DeleteXTree1(T->lchild); DeleteXTree1(T->rchild); free(T); } } //递归算法 void Search2(BiTree T,BiTree pre,int x){ //初始时,T为根,根的父结点pre为NULL。先序遍历 if(T){ if(T->data==x){ DeleteXTree2(T,pre); return ; } Search2(T->lchild,T,x); Search2(T->rchild,T,x); } } void DeleteXTree2(BiTree T,BiTree pre){ if(T){ DeleteXTree2(T->lchild,T); DeleteXTree2(T->rchild,T); if(pre && pre->lchild==T) pre->lchild=NULL; else if(pre && pre->lchild==T) pre->rchild=NULL; free(T); } } //查找结点p和结点q的最近公共祖先结点 //非递归算法 typedef struct { BiTree t; int tag; //tag=0表示左子女被访问,tag=1表示右子女被访问 } stack; stack S[MaxSize],S1[MaxSize]; BiTree Ancestor1(BiTree T,BiTree p,BiTree q){ top=-1; b=0; //标记是否已使p在q左边 while(T || top>-1){ while(T && T!=p && T!=q) while(T){ S[++top].t=T; S[top].tag=0; T=T->lchild; if(!b && T && T==p) //使p在q的左边 b=1; if(!b && T && T==q){ //使p在q的左边 b=1; temp=q; q=p; p=temp; } } while(top>-1 && S[top].tag==1){ if(S[top].t==p){ for(i=0;i<=top;i++) S1[i]=S[i]; top1=top; } if(S[top].t==q) for(i=top;i>=0;i--){ for(j=top1;j>=0;j--) if(S[i].t==S1[j].t) return S[i].t; } top--; } if(top>-1){ S[top].tag=1; T=S[top].t->rchild; } } return NULL; } //递归算法 BiTree r=NULL; BiTree Ancestor2(BiTree T,BiTree p,BiTree q){ if(T){ if(T==p) return 1; if(T==q) return -1; temp1=Ancestor2(T->lchild,p,q); temp2=Ancestor2(T->rchild,p,q); if(temp1 && temp2){ r=T; exit(0); } if(temp1){ //解决p(或q)是q(或p)的父亲的情况 r=temp1==1?p:q; return temp; } if(temp2){ //解决p(或q)是q(或p)的父亲的情况 r=temp2==1?p:q; return temp2; } //return 0; } //else // return 0; return 0; } //一棵满二叉树,已知其先序序列pre,求其后序序列post void PreToPost1(ElemType pre[],int l1,int h1,ElemType post[],int l2,int h2){ int half; if(h1>=l1){ post[h2]=pre[l1]; half=(h1-l1)/2; PreToPost(pre,l1+1,l1+half,post,l2,l2+half-1); //(l1+half)-(l1+1)=(l2+half-1)-(l2) PreToPost(pre,l1+half+1,h1,post,l2+half,h2-1); //(h1)-(l1+half+1)=(h2-1)-(l2+half) } } void PreToPost2(ElemType pre[],ElemType post[],int l,int h,int t=0){ //初始调用时t=0; if(h-l==1){ post[t++]=pre[l]; post[t++]=pre[h]; return ; } if(l<=h){ length=h-l; PreToPost2(pre,post,l+1,l+length/2,t); PreToPost2(pre,post,l+length/2+1,h,t); post[t++]=pre[l]; //这个千万不能放在前面!!! } } //将二叉树的叶结点按从左到右的顺序连成一个单链表,表对指针为head,二叉树按二叉链表方式存储,链接时用叶结点的右指针域来存放单链表指针 BiTree head=NULL,pre=NULL; BiTree InOrder(BiTree T){ //用二叉树的中序遍历(前序、后序等等遍历都行) if(T){ InOrder(T->lchild); if(!T->lchild && !T->rchild) if(!pre){ head=T; pre=T; } else{ pre->rchild=T; pre=T; } InOrder(T->rchild); pre->rchild=NULL; } return head; } //判断两棵二叉树是否相似,所谓二叉树T1和T2相似,指的是T1和T2都是空的二叉树或坦陈只有一个根结点,或者T1的左子树和T2的左子树是相似的且T1的右子树与T2的右子树是相似的。 int Similar1(BiTree T1,BiTree T2){ int leftS,rightS; if(!T1 && !T2) return 1; else if(!T1 || !T2) return 0; else{ leftS=Similar1(T1->lchild,T2->lchild); rightS=Similar1(T1->rchild,T2->rchild); return leftS&&rightS; } } int Similar2(BiTree T1,BiTree T2){ if(!T1 && !T2) return 1; if(T1 && T2){ if(!Similar2(T1->lchild,T2->lchild)) return 0; if(!Similar2(T1->rchild,T2->rchild)) return 0; return 1; } //else return 0; } //树的存储结构 //双亲表示法的存储结构 #define MAX_TREE_SIZE 100 typedef struct { ElemType data; int parent; } PTNode; typedef struct { PTNode nodes[MAX_TREE_SIZE]; int n; //结点数 } //孩子兄弟表示的存储结构 typedef struct CSNode{ ElemType data; struct CSNode *firstchild,*nextsibling; } CSNode,*CSTree; //求以孩子兄弟表示法存储的森林叶子结点数 //注意:没有孩子指针的才是叶子结点 int Leaves1(CSTree T){ if(!T) return 0; if(!T->firstchild) return 1+Leaves1(T->nextsibling); else return Leaves1(T->firstchild)+Leaves1(T->nextsibling); } int k=0; void Leaves2(CSTree T,int b=0){ //初始时b=0,用b=1指示是孩子指针 if(T){ Leaves2(T->firstchild,1); Leaves2(T->nextsibling,0); } else if(b) k++; } //用递归算法求以孩子兄弟表示法存储的树的深度 //也可用非递归的算法,类似于二叉树通过层序遍历求高度 int Height(CSTree T){ int hf,hn; if(!T) return 0; else{ hf=Height(T->firstchild); hn=Height(T->nextsibling); if(hf+1>hn) //特别注意这一点!!!对比求二叉树的高度!!! return hf+1; else return hn; } } //已知一棵树的层次序列以及每个结点的度,编写一个算法构造此树的孩子兄弟链表 CSTree CreateCSTree_Degree(CSTree T,DataType e[],int degree[],int n){ T=e[0]; q=T; q->nextsibling=NULL; j=1;i=0; while(i<n){ k=degree[i];q=e[i]; if(k){ q->firstchild=e[j++]; k--; q=q->firstchild; } while(k){ q->nextsibling=e[j++]; q->firstchild=NULL; q=q->nextsibling; k--; } q->firstchild=NULL; q->nextsibling=NULL; i++; } return T; } //树的应用:并查集 //并查集的结构定义 #define SIZE 100 int UFSets[SIZE]; //并查集的操作 void Initial(int S[]){ //初始化操作(S即为并查集) for(int i=0;i<size;i++) S[i]=-1; } void Find(int S[],int x){ //函数在并查集S中查找并返回包含元素x的树的根 while(S[x]>=0) x=S[x]; return x; } void Union(int S[],int Root1,int Root2){ //函数求两个不相交子集合的并集 S[Root2]=Root1; } //二叉排序树(BST) //二叉排序树的查找 //非递归算法 BSTNode *BST_Search1(BiTree T,ElemType key,BSTNode *&p){ p=NULL; while(T && key!=T->data){ p=T; //p指向被查找结点的双亲,用于插入和删除操作中 if(key<T->data) T=T->lchild; else T=T->rchild; } return T; } //递归算法 BSTNode *BST_Search2(BiTree T,ElemType key){ if(T){ if(T->data==key) return T; if(T->data>k)return BST_Search2(T->lchild,key); else return BST_Search2(T->rchild,key); } else return NULL; } //二叉排序树的插入 int BST_Insert(BiTree &T,ElemType k){ if(T==NULL){ T=(BiTree)malloc(sizeof(BSTNode)); T->key=k; T->lchild=T->rchild=NULL; return 1; } else if(k==T->key) return 0; else if(key<T->key) return BST_Insert(T->lchild,k); else return BST_Insert(T->rchild,k); } //二叉排序树的构造 void Create_BST(BiTree &T,ElemType str[],int n){ T=NULL; int i=0; while(i<n){ BST_Insert(T,str[i]); i++; } } //二叉排序树的删除 int BST_Delete(BiTree &T,ElemType k,BiTree p=NULL){ //p为父结点,初始为空 if(T){ if(T->data==key){ if(p) Solve(T,p); else free(T); return 1; } if(T->data>key) return BST_Delete(T->lchild,key,T); else return BST_Delete(T->rchild,key,T); } else return 0; } void Solve(BiTree T,BiTree p){ if(p->lchild==T) temp=&(p->lchild); else temp=&(p->rchild); if(T->lchild && !T->rchild){ *temp=T->lchild; free(T); } else if(T->rchild && !T->lchild){ *temp=T->rchild; free(T); } else{ //找右子树中T的中序直接后继 q=T->rchild; qp=T; //qp为p的前驱 while(q->lchild){ qp=q;q=q->lchild; } T->data=q->data; Solve(qp,q); /* //或找左子树中T的中序直接前驱 q=T->lchild;qp=T; while(q->rchild){ qp=q;q=q->rchild; } T->data=q->data; Solve(qp,q); */ } } //平衡二叉树 。。。 //判断一棵二叉树是否为二叉排序树 //对给定的二叉树进行中序遍历,如果始终能保持前一个值给后一个值小,则说明该二叉树是一棵二叉排序树 ElemType prekey=-32767; int JudgeBST1(BiTree T){ int b1,b2; if(!T) return 1; else{ b1=JudgeBST1(T->lchild); //访问左子树 if(!b1 || prekey>=T->data) return 0; prekey=T->data; //访问结点 b2=JudgeBST1(T->rchild); //访问右子树 return b2; } } int JudgeBST2(BiTree T,BiTree p){ //p为中序前驱,初始为零 if(T){ if(!JudgeBST(T->lchild,p)) return 0; if(!p){ p=T; return 1; } else if(p->data>=T->data) return 0; return JudgeBST(T->rchild,T); } else return 1; } //判断一棵二叉树是否为平衡二叉树 int Judge_AVL(BiTree T,int &h){ if(T){ t=h; if(!Judge_AVL(T->lchild,h)) return 0; tl=h; h=t; if(!Judge_AVL(T->rchild,h)) return 0; tr=h; if(tl>tr) h=tl+1; else h=tr+1; if(tl-tr>=2 ||tr-tl>=2) return 0; else return 1; } else{ h=0; return 1; } } //输入一个整数和一棵二元树。从树的根结点开始往下访问一直到叶子结点,所经过的所有结点 //形成一条路径。打印出路径和与data相等的所有路径。 #define MaxSize 50; int S[MaxSize]; //全局栈 int top=-1; void PrintData(BiTree T,ElemType data){ if(T){ S[++top]=T->data; if(data==T->data && !T->lchild && !T->rchild) for(i=0;i<=top;i++) print("%d ",S[i]); PrintData(T->lchild,data-T->data); top--; //注意传递是data不是引用,故这里不用data+T->data PrintData(T->rchild,data-T->data); top--; //注意传递是data不是引用,故这里不用data+T->data } } /* 总结:对于二叉树的题,一般都是二叉树遍历的问题。 */
原文地址:http://blog.csdn.net/o1101574955/article/details/44517233