二叉树的深度优先和广度优先遍历

图的深度优先搜索法是树的先根遍历的推广,它的基本思想是:从图G的某个顶点v0出发,访问v0,然后选择一个与v0相邻且没被访问过的顶点vi访问,再从vi出发选择一个与vi相邻且未被访问的顶点vj进行访问,依次继续。如果当前被访问过的顶点的所有邻接顶点都已被访问,则退回到已被访问的顶点序列中最后一个拥有未被访问的相邻顶点的顶点w,从w出发按同样的方法向前遍历,直到图中所有顶点都被访问。

图的广度优先搜索是树的按层次遍历的推广,它的基本思想是:首先访问初始点vi,并将其标记为已访问过,接着访问vi的所有未被访问过的邻接点vi1,vi2, …, vi t,并均标记已访问过,然后再按照vi1,vi2, …, vi t的次序,访问每一个顶点的所有未被访问过的邻接点,并均标记为已访问过,依次类推,直到图中所有和初始点vi有路径相通的顶点都被访问过为止。

二叉树的深度优先遍历的非递归的通用做法是采用栈,广度优先遍历的非递归的通用做法是采用队列。

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW  3
#define MAXSIZE 100 /* 存储空间初始分配量 */

typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef char ElemType; 

typedef struct BiTNode {
    ElemType data;
    struct BiTNode *lchild, *rchild; /* 左右孩子指针 */
} BiTNode, *BiTree;

/* 链栈结构 */
typedef struct StackNode
{
    BiTNode data;
    struct StackNode *next;
}StackNode,*LinkStackPtr;

typedef struct
{
    LinkStackPtr top;
    int count;
}LinkStack;

/*队列结构*/
typedef struct QNode {
    BiTNode data;
    struct QNode *next;
} QNode, *QueuePtr;

typedef struct {
    QueuePtr front, rear; /* 队头、队尾指针 */
} LinkQueue;

/* 链队列 的基本操作*/
void InitQueue(LinkQueue *Q)
{
    /* 构造一个空队列Q */
    (*Q).front = (*Q).rear = (QueuePtr)malloc(100*sizeof(QNode));
    if(!(*Q).front)
        exit(OVERFLOW);
    (*Q).front->next = NULL;
}
void DestroyQueue(LinkQueue *Q)
{
    /* 销毁队列Q(无论空否均可) */
    while((*Q).front) {
        (*Q).rear = (*Q).front->next;
        free((*Q).front);
        (*Q).front = (*Q).rear;
    }
}
Status QueueEmpty(LinkQueue Q)
{
    /* 若Q为空队列,则返回TRUE,否则返回FALSE */
    if(Q.front->next == NULL)
        return TRUE;
    else
        return FALSE;
}
Status GetHead_Q(LinkQueue Q, BiTNode *e) /* 避免与bo2-6.c重名 */
{
    /* 若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR */
    QueuePtr p;
    if(Q.front == Q.rear)
        return ERROR;
    p = Q.front->next;
    *e = p->data;
    return OK;
}
void EnQueue(LinkQueue *Q, BiTNode e)
{
    /* 插入元素e为Q的新的队尾元素 */
    QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
    if(!p) /* 存储分配失败 */
        exit(OVERFLOW);
    p->data =e;
    p->next = NULL;
    (*Q).rear->next = p;
    (*Q).rear = p;
}
Status DeQueue(LinkQueue *Q, BiTNode *e)
{
    /* 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */
    QueuePtr p;
    if((*Q).front == (*Q).rear)
        return ERROR;
    p = (*Q).front->next;
    *e = p->data;
    (*Q).front->next = p->next;
    if((*Q).rear == p)
        (*Q).rear = (*Q).front;
    free(p);
    return OK;
}
//#####################################################//

/* 链栈的基本操作*/
/*  构造一个空栈S */
Status InitStack(LinkStack *S)
{ 
    S->top = (LinkStackPtr)malloc(sizeof(StackNode));
    if(!S->top)
            return ERROR;
    S->top=NULL;
    S->count=0;
    return OK;
}

/* 把S置为空栈 */
Status ClearStack(LinkStack *S)
{ 
    LinkStackPtr p,q;
    p=S->top;
    while(p)
    {  
        q=p;
        p=p->next;
        free(q);
    } 
    S->count=0;
    return OK;
}

/* 若栈S为空栈,则返回TRUE,否则返回FALSE */
Status StackEmpty(LinkStack S)
{ 
    if (S.count==0)
        return TRUE;
    else
        return FALSE;
}

/* 返回S的元素个数,即栈的长度 */
int StackLength(LinkStack S)
{ 
    return S.count;
}

/* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
Status GetTop(LinkStack S, BiTNode *e)
{
    if (S.top==NULL)
        return ERROR;
    else
        *e=S.top->data;
    return OK;
}

/* 插入元素e为新的栈顶元素 */
Status Push(LinkStack *S, BiTNode e)
{
    LinkStackPtr s=(LinkStackPtr)malloc(sizeof(StackNode)); 
    s->data=e; 
    s->next=S->top;	/* 把当前的栈顶元素赋值给新结点的直接后继*/
    S->top=s;         /* 将新的结点s赋值给栈顶指针*/
    S->count++;
    return OK;
}

/* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
Status Pop(LinkStack *S, BiTNode *e)
{ 
    LinkStackPtr p;
    if(StackEmpty(*S))
    	return ERROR;
    *e=S->top->data;
    p=S->top;				/* 将栈顶结点赋值给p */
    S->top=S->top->next;    /* 使得栈顶指针下移一位,指向后一结点*/
    free(p);                /* 释放结点p */        
    S->count--;
    return OK;
}

/* 用于构造二叉树********************************** */
int count=1;
typedef char String[100]; /*  0号单元存放串的长度 */
String str;

Status StrAssign(String T,char *chars)
{ 
	int i;
	if(strlen(chars)>MAXSIZE)
		return ERROR;
	else
	{
		T[0]=strlen(chars);
		for(i=1;i<=T[0];i++)
			T[i]=*(chars+i-1);
		return OK;
	}
}
/* ************************************************ */

void CreateBiTree(BiTree *T)
{
    /* 按先序次序输入二叉树中结点的值(此处字符型)*/
    /* 构造二叉链表表示的二叉树T。 */
    ElemType ch;
    ch=str[count++];
    if(ch == '#') /* 空 */
        *T = NULL;
    else {
        *T = (BiTree)malloc(sizeof(BiTNode)); /* 生成根结点 */
        if(!*T)
            exit(OVERFLOW);
        (*T)->data = ch;
        CreateBiTree(&(*T)->lchild); /* 构造左子树 */
        CreateBiTree(&(*T)->rchild); /* 构造右子树 */
    }
}

void InitBiTree(BiTree *T)
{
    /* 操作结果:构造空二叉树T */
    *T = NULL;
}

void DestroyBiTree(BiTree *T)
{
    /* 初始条件:二叉树T存在。操作结果:销毁二叉树T */
    if(*T) { /* 非空树 */
        if((*T)->lchild) /* 有左孩子 */
            DestroyBiTree(&(*T)->lchild); /* 销毁左孩子子树 */
        if((*T)->rchild) /* 有右孩子 */
            DestroyBiTree(&(*T)->rchild); /* 销毁右孩子子树 */
        free(*T); /* 释放根结点 */
        *T = NULL; /* 空指针赋0 */
    }
}

/*广度优先遍历,层序*/
void BFSTree(BiTree T)
{
	LinkQueue Q;
	BiTNode e;
	InitQueue(&Q);
	EnQueue(&Q,*T);
	printf("BFSTree: ");
	while(!QueueEmpty( Q)){
		DeQueue(&Q, &e);
		printf("%c",e.data);
		if(T->lchild != NULL)
		{
			EnQueue(&Q, *(T->lchild));
		}
		if(T->rchild != NULL)
		{
			EnQueue(&Q, *(T->rchild));
		}
		GetHead_Q(Q,  &e);
		T = &e;		
	}
	printf("\n");
	DestroyQueue(&Q);
}

/*深度优先遍历,前序*/
void DFSTree(BiTree T)
{
	LinkStack S;
	BiTNode e;
	InitStack(&S);
	Push(&S, *T);
	printf("DFSTree: ");
	while(!StackEmpty(S)){
		Pop(&S, &e);
		printf("%c",e.data);
		if(T->rchild != NULL)
		{
			Push(&S, *(T->rchild));
		}
		if(T->lchild != NULL)
		{
			Push(&S, *(T->lchild));
		}	
		GetTop(S, &e);
		T = &e;	
	}
	printf("\n");
	ClearStack(&S);
}


int main(void)
{
	BiTree t;

	InitBiTree(&t);
	StrAssign(str,"abd##e##cf##g##");

	CreateBiTree(&t);
	BFSTree(t);
	DFSTree(t);
	DestroyBiTree(&t);
}
结果:

BFSTree:abcdefg

DFSTree:abdecfg


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值