[功能模块]
//二元树检索与周游算法的实现(VC++6.0调试通过)
#include <iostream>
#define n 11 //0号结点不用
typedef struct Node{
int num; // 节点编号
struct Node *lch;
struct Node *rch;
}node,*BinTree;
struct Neighborhood {
int num; // 节点编号
struct Neighborhood *next;
}*NeighborList[n]; // n个节点的邻接表,动态生成并初始化
//静态初始化n个节点的邻接矩阵
int NeighborMetrix[n][n]={ {0,0,0,0,0,0,0,0,0,0,0},{0,0,1,1,0,0,0,0,0,0,0},
{0,0,0,0,1,1,0,0,0,0,0},{0,0,0,0,0,0,1,1,0,0,0},{0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,1,1,0},{0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,1},
{0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0} };
void CreatBinTree(BinTree *T) //先序动态生成二叉树
{ int data;
scanf("%d",&data);
if(data==0) *T=NULL; //输入0表示空树
else
{
*T=(BinTree)malloc(sizeof(node));
(*T)->num=data;
CreatBinTree(&(*T)->lch);
CreatBinTree(&(*T)->rch);
}
}
//动态生成并初始化邻接表
void CreatNeighborList(Neighborhood * NeighborList[])
{ int i,j;
Neighborhood *p,*q;
printf("初始化邻接表成功!/n");
for(i=1;i<=10;i++)
{
NeighborList[i]=(Neighborhood *)malloc(sizeof(Neighborhood));
NeighborList[i]->num=i; //初始化邻接表行向量的值
NeighborList[i]->next=NULL;
}
for(i=1;i<=10;i++)
{
printf("创建第 %d 个结点的邻接表(0表示NULL):",i);
while(1)
{
scanf("%d",&j);
if(j==0) break; //该结点没有邻接结点
p=(Neighborhood *)malloc(sizeof(Neighborhood));
p->next=NULL;
p->num=j;
if(NeighborList[i]->next==NULL)
NeighborList[i]->next=p; //指向第一个邻接结点
else
{
q=NeighborList[i]->next;
while(q->next!=NULL) q=q->next; //找当前最后一个邻接结点
q->next=p; //挂在当前结点的后面
}
}
}
}
//先根序周游并输出二元树的节点序列
void PreOrderTraverse(BinTree T)
{
if(T!=NULL)
{
printf("%d/t",T->num);
PreOrderTraverse(T->lch);
PreOrderTraverse(T->rch);
}
}
//中根序周游并输出二元树的节点序列
void InOrderTraverse(BinTree T)
{
if(T!=NULL)
{
InOrderTraverse(T->lch);
printf("%d/t",T->num);
InOrderTraverse(T->rch);
}
}
//后根序周游并输出二元树的节点序列
void PostOrderTraverse(BinTree T)
{
if(T!=NULL)
{
PostOrderTraverse(T->lch);
PostOrderTraverse(T->rch);
printf("%d/t",T->num);
}
}
//根据二元树的邻接表表示,按宽度优先检索输出二元树的节点序列
void BFS( Neighborhood * NeighborList[])
{
int i,vo,visited[n],Q[n];
int front=0,rear=0;
Neighborhood *p;
for(i=1;i<=10;i++) visited[i]=0;
printf("输入开始宽度优先检索的结点:");
scanf("%d",&vo);
Q[rear++]=vo;
printf("宽度优先检索的结点序列为:/n");
printf("%d/t",vo); //输出开始检索的结点
visited[vo]=1;
while(front!=rear)
{
vo=Q[front++]; //取队头元素
p=NeighborList[vo]->next;
while(p!=NULL)
{
if(visited[p->num]==0) //如果未被访问过
{
Q[rear++]=p->num; //入队列
printf("%d/t",p->num); //访问该结点
visited[p->num]=1;
}
p=p->next; //找下一个邻接结点
}
}
}
//根据二元树的邻接矩阵表示,按深度优先检索输出二元树的节点序列
void DFS(int NeighborMetrix[][n],int vo)
{
int i;
printf("%d/t",vo); //访问该结点
for(i=1;i<=10;i++)
if(NeighborMetrix[vo][i]==1) //如果邻接矩阵中有边
{
NeighborMetrix[vo][i]=0; //访问后将该边置0
DFS(NeighborMetrix , i); //以找到的邻接结点继续检索
}
}
// 释放动态分配的二元树节点空间
void DeleteBinTree(BinTree T)
{
if(T!=NULL) //通过后根序遍历来释放
{
DeleteBinTree(T->lch);
DeleteBinTree(T->rch);
free(T);
}
}
//释放动态分配的邻接表节点空间(通过再次宽度优先检索来释放)
void DeleteNeighborList(Neighborhood * NeighborList[])
{
int i,vo=1,visited[n],Q[n];
int front=0,rear=0;
Neighborhood *p,*q;
for(i=1;i<=10;i++) visited[i]=0;
Q[rear++]=vo;
visited[vo]=1;
while(front!=rear)
{
vo=Q[front++]; //取队头元素
p=NeighborList[vo]->next;
free(NeighborList[vo]); //每次释放队头元素的空间
while(p!=NULL)
{
if(visited[p->num]==0) //如果未被访问过
{
Q[rear++]=p->num; //入队列
visited[p->num]=1;
}
p=p->next; //找下一个邻接结点
}
}
}
void main()
{
int vo;
BinTree t;
Neighborhood * NeighborList[n] ;
printf("先序创建二元树(0表示NULL):/n");
CreatBinTree(&t);
printf("先根序周游二元树的节点序列为:/n");
PreOrderTraverse(t);
printf("中根序周游二元树的节点序列为:/n");
InOrderTraverse(t);
printf("后根序周游二元树的节点序列为:/n");
PostOrderTraverse(t);
printf("输入开始深度优先检索的结点:");
scanf("%d",&vo);
printf("深度优先检索的结点序列为:/n");
DFS(NeighborMetrix , vo);
printf("创建二元树的邻接表:/n");
CreatNeighborList(NeighborList);
BFS(NeighborList);
printf("动态分配的二元树节点空间已释放!/n");
DeleteBinTree(t);
printf("动态分配的邻接表节点空间已释放!/n");
DeleteNeighborList(NeighborList);
}
[测试方案]
假设有以下二元树,可知:
先根序周游二元树的节点序列为:
1 2 4 5 8 9 3 6 7 10
中根序周游二元树的节点序列为:
4 2 8 5 9 1 6 3 7 10
后根序周游二元树的节点序列为:
4 8 9 5 2 6 10 7 3 1
深度优先检索的结点序列为:
1 2 4 5 8 9 3 6 7 10
宽度优先检索的结点序列为:
1 2 3 4 5 6 7 8 9 10
按以上数据进行测试,程序的运行结果如下: