码迷,mamicode.com
首页 > 其他好文 > 详细

二叉树小结

时间:2015-03-21 18:43:22      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:c代码   算法   数据结构   二叉树   

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
	}
}
/*
	总结:对于二叉树的题,一般都是二叉树遍历的问题。
*/

二叉树小结

标签:c代码   算法   数据结构   二叉树   

原文地址:http://blog.csdn.net/o1101574955/article/details/44517233

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!