数据结构上机实验报告四.docx
《数据结构上机实验报告四.docx》由会员分享,可在线阅读,更多相关《数据结构上机实验报告四.docx(11页珍藏版)》请在冰豆网上搜索。
数据结构上机实验报告四
“计算机软件技术基础”课程实验报告(四)
实验名称:
树和图结构
班级_390712_姓名_董晶晶_学号39071203_实验日期:
10-11-28
实验机时:
3学时实验成绩:
-------------------------------------------------------------------------------
一.实验目的:
1、掌握二叉树的存储方法和遍历操作算法;
2、掌握图的存储方法和遍历操作算法。
二.实验内容:
1、建立二叉树,并实现该二叉树的层次遍历。
2、建立无向图的邻接表,并实现该图的广度优先遍历。
三.程序及注释:
二叉树
总体思路:
二叉树一广义表的形式输入,根据相关的约定和说明,需用到switch语句判断输入信息,一个标志变量flag(标记某结点是双亲结点的左孩子还是右孩子,约定左为1右为2),一个假设空间足够、采用顺序存储结构的堆栈STACK[0..Maxsize-1](保存双亲结点的地址)。
#include
#include
#defineMaxSize100
typedefstructnode
{chardata;
structnode*lchild,*rchild;
}BTNode,*BTREE;/*二叉树的定义*/
BTREECREATEBT();
intCOUNTLEAF(BTREET);
voidPREORDER(BTREET);
voidINORDER(BTREET);
voidPOSTORDER(BTREET);
voidLAYERORDER(BTREET);
voidmain()
{inta;
BTREET=NULL;
T=CREATEBT();/*建立二叉树*/
a=COUNTLEAF(T);/*统计叶子结点的个数*/
printf("Thenumberofleavesis:
%d\n",a);
PREORDER(T);/*前序遍历*/
printf("\n");
INORDER(T);/*中序遍历*/
printf("\n");
POSTORDER(T);/*后续遍历*/
printf("\n");
LAYERORDER(T);/*层次遍历*/
}
BTREECREATEBT()
{BTREESTACK[MaxSize],p,T=NULL;
charch;
intflag,top=-1;
while
(1)
{scanf("%c",&ch);/*取广义表中一个元素*/
switch(ch)
{default:
p=(BTREE)malloc(sizeof(BTNode));
p->data=ch;
p->lchild=NULL;
p->rchild=NULL;/*建立一个新节点*/
if(T==NULL)/*p所指结点为根节点*/
T=p;
elseif(flag==1)
STACK[top]->lchild=p;/*p所指结点为根的左孩子*/
else
STACK[top]->rchild=p;/*p所指结点为根的右孩子*/
break;
case'(':
STACK[++top]=p;/*取到左括号,进栈*/
flag=1;/*置标志1*/
break;
case')':
top--;/*取到右括号,退栈*/
break;
case',':
flag=2;/*取到逗号,置标志2*/
break;
case'@':
return(T);/*取到结束符合'@'*/
}
}
}
intCOUNTLEAF(BTREET)/*计算叶节点的个数*/
{if(T==NULL)
return0;
if(T->lchild==NULL&&T->rchild==NULL)
return1;
return(COUNTLEAF(T->lchild)+COUNTLEAF(T->rchild));
}
voidPREORDER(BTREET)
{if(T!
=NULL)
{
printf("%c",T->data);/*访问T所指结点*/
PREORDER(T->lchild);/*遍历T所指结点的左子树*/
PREORDER(T->rchild);/*遍历T所指结点的右子树*/
}
}
voidINORDER(BTREET)
{if(T!
=NULL)
{INORDER(T->lchild);/*遍历T所指结点的左子树*/
printf("%c",T->data);/*访问T所指结点*/
INORDER(T->rchild);/*遍历T所指结点的右子树*/
}
}
voidPOSTORDER(BTREET)
{if(T!
=NULL)
{POSTORDER(T->lchild);/*遍历T所指结点的左子树*/
POSTORDER(T->rchild);/*遍历T所指结点的右子树*/
printf("%c",T->data);/*访问T所指结点*/
}
}
voidLAYERORDER(BTREET)
{BTREEQUEUE[MaxSize],p;
intfront,rear;
if(T!
=NULL)
{QUEUE[0]=T;/*根结点进队*/
front=-1;/*队头指针初始化*/
rear=0;/*队尾指针初始化*/
while(front{p=QUEUE[++front];/*访问根结点*/
printf("%c",p->data);
if(p->lchild!
=NULL)/*左孩子不为空*/
QUEUE[++rear]=p->lchild;/*左孩子进队*/
if(p->rchild!
=NULL)/*右孩子不为空*/
QUEUE[++rear]=p->rchild;/*右孩子进队*/
}
}
}
运行结果:
调试总结:
1)二叉树的建立;
2)遍历时的递归算法;
图
总体思路:
从图中指定顶点v出发,访问v以后依次访问v的各个未被访问的邻接点,然后从邻接点出发按照同样的原则依次访问未被访问过的点······直到图中所有的点都被访问过。
因此,实现此过程需要设置一个队列结构。
#defineN20
#defineM100
#include
#include
typedefstructgraph_edge
{intadjvex;
structgraph_edge*next;
}ELink;/*定义边的数据类型*/
typedefstructgraph_node
{charvertex[5];
structgraph_edge*link;
}NLink;/*定义顶点的数据类型*/
voidCREATGRAPH(NLinkNode[N],intn,inte);
voidTRAVERSE_BFS(NLinkNode[N],intQUEUE[],intn);
voidBFS(NLinkNode[N],intQUEUE[],intk);
intADDQUEUE(intQUEUE[],intk);
intDELQUEUE(intQUEUE[]);
intEMPTYQUEUE();
intfront=-1;/*定义全局变量,对队头初始化*/
intrear=-1;/*定义全局变量,对队尾进行初始化*/
voidmain()
{NLinkNode[N];
intn,e;
intQUEUE[M]={0};/*构造队列,赋值为0*/
printf("请输入顶点个数n\n");/*输入顶点个数*/
scanf("%d",&n);
printf("请输入表示边的顶点偶对个数e\n");
/*输入边的顶点偶对的个数,无向图为边数的两倍*/
scanf("%d",&e);
CREATGRAPH(Node,n,e);/*建立图*/
TRAVERSE_BFS(Node,QUEUE,n);/*广度搜索*/
}
voidCREATGRAPH(NLinkNode[N],intn,inte)
{ELink*p,*q;
inti,j,k;
for(i=0;i{
printf("请输入顶点的数据信息\n");/*输入顶点名称*/
scanf("%s",Node[i].vertex);
Node[i].link=NULL;/*把顶点的指针域清零*/
}
for(k=0;k{printf("输入边的两顶点下标值\n");/*输入顶点对应下标值*/
scanf("%d,%d",&i,&j);
p=(ELink*)malloc(sizeof(ELink));
p->adjvex=j;/*建立边表*/
p->next=NULL;
if(!
Node[i].link)
{Node[i].link=p;/*建立顶点与边的链接*/
}
else
{q=Node[i].link;
while(q->next)/*顶点的第一个邻接点指针域不空*/
q=q->next;/*指向下一个结点*/
q->next=p;/*建立第一个结点与该结点的链接*/
}
}
}
voidTRAVERSE_BFS(NLinkNode[N],intQUEUE[],intn)
{inti;
intvisited[M];
for(i=0;ivisited[i]=0;/*标记数组赋初值(清零)*/
for(i=0;iif(visited[i]==0)
BFS(Node,QUEUE,i,visited);
}
voidBFS(NLinkNode[N],intQUEUE[],intv,intvisited[M])
{ELink*p;
if(!
visited[v])
{printf("nodevisited:
%s\n",Node[v].vertex);/访问顶点v*/
visited[v]=1;/*顶点v对应的访问标记置为1*/
ADDQUEUE(QUEUE,v);//访问过的顶点K入队
}
while(!
EMPTYQUEUE())
{v=DELQUEUE(QUEUE);/*退出队头元素送i*/
p=Node[v].link;/*访问v的邻接点*/
while(p!
=NULL)
{
if(!
visited[p->adjvex])
{
printf("nodevisited:
%s\n",Node[p->adjvex].vertex);/*把邻接点打印出来*/
visited[p->adjvex]=1;
ADDQUEUE(QUEUE,p->adjvex);/*把V的邻接点入队*/
}
p=p->next;//访问v的下一个邻接点
}
}
}
intADDQUEUE(intQUEUE[],intk)
{if((rear+1)%M==front)
return0;/*循环队列已满,插入失败,返回0*/
else
{QUEUE[++rear%M]=k;
return1;/*循环队列未满,插入成功,返回1*/
}
}
intDELQUEUE(intQUEUE[])
{intitem=0;
if(front==rear)
return0;/*循环队列为空,删除失败,返回0*/
else
{front=(front+1)%M;
item=QUEUE[front];
returnitem;/*循环队列未空,删除成功,返回1*/
}
}
intEMPTYQUEUE()
{returnfront==rear;
}
运行结果:
调试总结:
1)图的邻接表存储;
2)图的广度优先遍历。