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(q,qp);
/* //或找左子树中T的中序直接前驱
q=T->lchild;qp=T;
while(q->rchild){
qp=q;q=q->rchild;
}
T->data=q->data;
Solve(q,qp);
*/
}
}
//平衡二叉树
。。。
//判断一棵二叉树是否为二叉排序树
//对给定的二叉树进行中序遍历,如果始终能保持前一个值给后一个值小,则说明该二叉树是一棵二叉排序树
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
}
}
/*
总结:对于二叉树的题,一般都是二叉树遍历的问题。
*/
二叉树小结
最新推荐文章于 2023-07-18 20:50:28 发布