数据结构 广义表的建立与输出
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
q->data=NULL;
p->sublist=q;//当前结点的sublist域指向新申请的结点
p=q;//令新申请的结点成为当前结点
}
else
{
if(s[j]==',')//若字符为',',执行以下操作
{
q=(GLNode *)malloc(sizeof(GLNode));//申请新结点
q->tag=0;//初始化新结点,标记域赋值为0,data域赋空字符
{
if(s[j]=='(')//若字符为'(',执行以下操作
{
p->tag=1;//当前结点的标记域赋值为1,表示存在子表
K.top++;//当前结点的指针进栈
K.pin[K.top]=p;
q=(GLNode *)malloc(sizeof(GLNode));//申请新结点
q->tag=0;//初始化新结点,标记域赋值为0,data域赋空字符
申请新结点并令其标记域为0,data域为空字符
当前结点p的sublist域指向新结点q
将新结点指针赋给当前结点p
}
◎若字符为',',执行以下操作
{
申请新结点并令其标记域为0,data域为空字符
当前结点p的next域指向新结点q
将新结点指针赋给当前结点p
}
◎若字符为')',执行以下操作
{
令当前结点p的next域为空
char data;//data用于存储广义表中的字母
struct LNode *sublist,*next;//sublist为指向该结点下一层的指针,next为指向该结点同一层的指针
}GLNode;
//——————————————————————————————————————————
typedef struct//顺序栈的类型描述
(二)每个模块的分析
1、主程序模块
main()
{
①定义数组,存储输入的字符串
②定义并申请头结点
③初始化顺序栈
④while(1)
{
调用输入广义表的函数,建立广义表的链式存储结构
调用输出广义表的函数,输出所建立的广义表
选择是否继续,若是,则重新执行循环中的操作;若否,则退出循环
}
}
2、建立广义表的函数
void Create(GLNode *G,ቤተ መጻሕፍቲ ባይዱeqStack &K,char s[])
1、程序使用说明:
(1)本程序运行环境为Visual C++ 6.0;
(2)根据界面提示进行操作,注意输入的字符为西文字符
2、测试结果与分析:
页面提示“输入广义表:”
输入“((),a,b,((c,(d,()))),((())))”,按回车确定,页面显示如下:
“输出结果为:((),a,b,((c,(d,()))),((())))
{
①定义表示当前结点的指针p,和表示新申请结点的指针q
令p指向头结点,且头结点的next域为空。
②输入广义表
③从头到尾扫描输入的字符,进入以下循环,当遇到空字符时结束循环
for(j=0;s[j]!='\0';j++)
{
◎若字符为'(',执行以下操作
{
当前结点的标记域赋值为1,表示存在子表
当前结点的指针进栈
每个结点的形式如下图所示。
tag为标记域:若tag=0,表示该结点的sublist域不为空,若tag=1,表示该结点为表结点,则sublist域中存放相应子表第一个元素对应结点的地址;
data域:存放广义表中的字母;
sublist域:存放相应子表第一个元素对应结点的地址;
next域:存放与本元素同一层的下一个元素所在结点的地址,当本元素是所在层的最后一个元素时,next域为空。
输出结果为:((),a,b,((c,(d,()))),((())))
是否继续?(是,输入1;否,输入0):1
输入广义表:
广义表未建立
是否继续?(是,输入1;否,输入0):0
Press any key to continue
二 概要设计
1、广义表是一种递归的数据结构,因此很难为每个广义表分配固定大小的存储空间,所以其存储结构采用动态链式结构。
4、运行界面
五、实验总结
因为本次实验花费了很多时间思考算法,所以在编写程序上花费的时间不算太多,我在10月26日晚上写完代码,并于当天修改正确。
在本次编写程序过程中,问题主要发生在输出广义表的函数上,反复查找思路中不严谨的地方,结合对输入广义表的函数的修改,一点一点地改进,最后才得以修改正确。在上次试验完成后便开始思考和与别人讨论可以实现题目要求的算法,最初的算法不够完善,主要只考虑了简单的广义表,但是对广义表中出现多层括号等一些特殊情况的思考不够深入,在与同学进行了讨论后,最后确定下来本实验中所采用的思路。因为所用教材上对广义表的讲解很少,所以参考了一些其它资料。
由上测试结果分析得,该程序功能满足题目要求。
3、调试过程中遇到的问题及解决方法
①当代码编写完成后,编译过程出现了很多小错误,比如语句末尾漏掉分号,使用了某些变量却未定义,但这些问题很快发现并及时纠正;
②在建立广义表的函数中,建立结点后对其data域赋值不完整,一些特殊结点指针域的说明也不完整,导致输出结果有问题。于是回头进一步梳理思路,是细节部分更加严谨,最后修改正确;
是否继续?(是,输入1;否,输入0):”
输入序号“1”,按回车确定,表示继续操作。
页面提示“输入广义表:”
不输入广义表,直接按回车确定,则页面显示如下:
“广义表未建立
是否继续?(是,输入1;否,输入0):”
输入序号“0”,按回车确定,表示结束操作,页面显示如下:
“Press any key to continue”
{
printf("输出结果为:");//提示以下结果为输出的广义表
实验成绩:99
指导教师签名:
批阅日期:2013.11.4
代码:
# include<stdio.h>
# include<stdlib.h>
//——————————————————————————————————————————
typedef struct LNode//广义表结点的类型描述
{
int tag;//tag为结点中的标记域
2、广义表的建立
本程序中利用数组存储所输入的广义表,然后从头到尾扫描数组中的每一个字符根据字符的不同分别执行不同的操作,并用一个存储结点指针的栈辅助完成。在扫描前先申请一个结点作为头结点,也是当前指针所指结点,在广义表的建立的过程中,每次申请一个新结点,需对其进行初始化,即令标记域为0,data域为空。按照本程序的思路,广义表(a,(b,c),())的链式存储结构如下图所示。广义表建立的具体过程见详细设计部分。
若当前结点p的next域不为空,表示不是该层的结束,输出','
将当前结点p的next域所指结点赋给p
}
}
◎若当前结点指针为空,执行以下操作
{
输出')'
出栈,将栈顶元素赋给当前结点p,
若当前结点p的next域不为空,表示不是该层的结束,输出','
将当前结点p的next域所指结点赋给p
}
}
}
四 使用说明、测试分析及结果
本次实验,我很感谢老师和同学对我的指点。通过本次实验,对广义表的存储结构有了更深的认识,对一些细节更加理解,收获了很多。
教师评语:
首先,我强调一下要注意细节,不论是对你而言简单的部分还是复杂的部分,这些都会影响你程序的编译和调试,另外,在充分考虑并设计好程序后在进行编写操作这是一个良好的习惯,这样能够提高你的编程效率,降低出错的可能性,当然,最好的话细分模块是一个比较好的习惯,当然这主要是针对大型程序而言。
一、需求分析
1、输入的形式和输入值的范围:根据提示,输入广义表,按回车结束。
2、输出的形式:输出结果为上一步所输入的广义表。
3、程序所能达到的功能:输入广义表后,该程序可以建立广义表的链式存储结构,之后按照一定的顺序访问结点并输出相应的值,从而完成广义表的输出。
4、测试数据:
输入广义表:((),a,b,((c,(d,()))),((())))
输出广义表的函数:Display(GLNode *G,SeqStack &K)
主函数:main( )
函数的调用关系如下图所示:
三 详细设计
(一)元素类型、结点类型
1、广义表结点的类型描述
typedef struct LNode
{
int tag;//tag为结点中的标记域
char data;//data用于存储广义表中的字母
{
GLNode *p,*q;//p指针指向当前结点,q指针指向新申请的结点
int j;//j用于标记输入的字符在数组中的位置
printf("输入广义表:");//提示输入广义表的
gets(s);
p=G;//令p指向头结点
p->next=NULL;//头结点的next域为空
for(j=0;s[j]!='\0';j++)//进入循环,建立广义表
③更多的问题出现在了输出广义表的函数中,刚开始出现广义表的输出少括号或多括号的情况,这里有一部分原因是建立广义表的函数的问题,两部分同时作的修改。之后又出现输入复杂的广义表时,部分字母不能输出,多重括号的输出也只能输出两个,认真分析后,发现还是对广义表中右括号的处理不够完善,于是在输出时,进一步细化了输出结果的条件,比如对“(a,b)”和“()”这两种形式采取不同的输出条件和输出结果。在不断地查找问题和完善中,最终修改正确。
q->data=NULL;
p->next=q;//当前结点的next域指向新申请的结点
p=q;//令新申请的结点成为当前结点
}
else
{
if(s[j]==')')//若字符为')',执行以下操作
{
p->next=NULL;//令当前结点的next域为空
p=K.pin[K.top];//出栈,令当前结点为栈顶元素
{
GLNode *pin[20];//指针数组,用于存储广义表结点指针
int top;//栈顶指针
}SeqStack;
//——————————————————————————————————————————
void Create(GLNode *G,SeqStack &K,char s[])//建立广义表函数
③将当前结点p的sublist域所指结点赋给p。
④当栈不空时执行以下操作
while(K.top!=-1)
{
◎若当前结点指针p不为空,执行以下操作
{
若当前结点标记域为1,执行以下操作
{
输出'(',并当前结点指针p入栈
将当前结点p的sublist域所指结点赋给p
}
若当前结点标记域为0,执行以下操作
{
若当前结点p的date域存有字母则输出该字母
struct LNode *sublist,*next;//sublist为指向下层的指针,next为指向同一层的指针
}GLNode;
2、顺序栈的类型描述
typedef struct
{
GLNode *pin[20];//指针数组,用于存储广义表结点指针
int top;//栈顶指针
}SeqStack;
《数据结构》实验报告
◎实验题目:广义表的建立与输出
◎实验目的:1、掌握使用Visual C++6.0上机调试程序的基本方法;
2、掌握广义表的存储结构,学会广义表的建立与输出;
3、提高自己分析问题和解决问题的能力,在实践中理解教材上的理论。
◎实验内容:利用链式存储结构建立广义表,然后输出该广义表,在本实验中不使用递归的方法,而是用一个栈存储结点的指针,以此完成实验要求。
K.top--;
}
else//若字符为字母,执行以下操作
{
p->data=s[j];//令当前结点的data域为该字母
p->sublist=NULL;//当前结点的sublist域为空
}
}
}
}
}
//——————————————————————————————————————————
void Display(GLNode *G,SeqStack &K)//输出广义表的函数
3、广义表的输出
在广义表的输出过程中也需利用一个存储结点指针的栈辅助完成,初始时栈为空,广义表输出结束后栈也为空,所以在开始时将头结点入栈,之后根据当前指针所指结点的特性的不同执行不同的操作,以栈空作为广义表输出的结束条件。广义表输出的具体过程见详细设计部分。
4、本程序的基本操作和模块:
建立广义表的函数:Create(GLNode *G,SeqStack &K,char s[])
出栈,将栈顶元素赋给当前结点q
}
◎若字符为字母,执行以下操作
{
令当前结点p的data域为该字母
令当前结点的sublist域为空
}
}
}
3、输出广义表的函数
void Display(GLNode *G,SeqStack &K)
{
①定义表示当前结点的指针p,并令p指向头结点。
②指向头结点的指针p入栈,使栈不空,输出广义表里的第一个左括号'('。
p->sublist=q;//当前结点的sublist域指向新申请的结点
p=q;//令新申请的结点成为当前结点
}
else
{
if(s[j]==',')//若字符为',',执行以下操作
{
q=(GLNode *)malloc(sizeof(GLNode));//申请新结点
q->tag=0;//初始化新结点,标记域赋值为0,data域赋空字符
{
if(s[j]=='(')//若字符为'(',执行以下操作
{
p->tag=1;//当前结点的标记域赋值为1,表示存在子表
K.top++;//当前结点的指针进栈
K.pin[K.top]=p;
q=(GLNode *)malloc(sizeof(GLNode));//申请新结点
q->tag=0;//初始化新结点,标记域赋值为0,data域赋空字符
申请新结点并令其标记域为0,data域为空字符
当前结点p的sublist域指向新结点q
将新结点指针赋给当前结点p
}
◎若字符为',',执行以下操作
{
申请新结点并令其标记域为0,data域为空字符
当前结点p的next域指向新结点q
将新结点指针赋给当前结点p
}
◎若字符为')',执行以下操作
{
令当前结点p的next域为空
char data;//data用于存储广义表中的字母
struct LNode *sublist,*next;//sublist为指向该结点下一层的指针,next为指向该结点同一层的指针
}GLNode;
//——————————————————————————————————————————
typedef struct//顺序栈的类型描述
(二)每个模块的分析
1、主程序模块
main()
{
①定义数组,存储输入的字符串
②定义并申请头结点
③初始化顺序栈
④while(1)
{
调用输入广义表的函数,建立广义表的链式存储结构
调用输出广义表的函数,输出所建立的广义表
选择是否继续,若是,则重新执行循环中的操作;若否,则退出循环
}
}
2、建立广义表的函数
void Create(GLNode *G,ቤተ መጻሕፍቲ ባይዱeqStack &K,char s[])
1、程序使用说明:
(1)本程序运行环境为Visual C++ 6.0;
(2)根据界面提示进行操作,注意输入的字符为西文字符
2、测试结果与分析:
页面提示“输入广义表:”
输入“((),a,b,((c,(d,()))),((())))”,按回车确定,页面显示如下:
“输出结果为:((),a,b,((c,(d,()))),((())))
{
①定义表示当前结点的指针p,和表示新申请结点的指针q
令p指向头结点,且头结点的next域为空。
②输入广义表
③从头到尾扫描输入的字符,进入以下循环,当遇到空字符时结束循环
for(j=0;s[j]!='\0';j++)
{
◎若字符为'(',执行以下操作
{
当前结点的标记域赋值为1,表示存在子表
当前结点的指针进栈
每个结点的形式如下图所示。
tag为标记域:若tag=0,表示该结点的sublist域不为空,若tag=1,表示该结点为表结点,则sublist域中存放相应子表第一个元素对应结点的地址;
data域:存放广义表中的字母;
sublist域:存放相应子表第一个元素对应结点的地址;
next域:存放与本元素同一层的下一个元素所在结点的地址,当本元素是所在层的最后一个元素时,next域为空。
输出结果为:((),a,b,((c,(d,()))),((())))
是否继续?(是,输入1;否,输入0):1
输入广义表:
广义表未建立
是否继续?(是,输入1;否,输入0):0
Press any key to continue
二 概要设计
1、广义表是一种递归的数据结构,因此很难为每个广义表分配固定大小的存储空间,所以其存储结构采用动态链式结构。
4、运行界面
五、实验总结
因为本次实验花费了很多时间思考算法,所以在编写程序上花费的时间不算太多,我在10月26日晚上写完代码,并于当天修改正确。
在本次编写程序过程中,问题主要发生在输出广义表的函数上,反复查找思路中不严谨的地方,结合对输入广义表的函数的修改,一点一点地改进,最后才得以修改正确。在上次试验完成后便开始思考和与别人讨论可以实现题目要求的算法,最初的算法不够完善,主要只考虑了简单的广义表,但是对广义表中出现多层括号等一些特殊情况的思考不够深入,在与同学进行了讨论后,最后确定下来本实验中所采用的思路。因为所用教材上对广义表的讲解很少,所以参考了一些其它资料。
由上测试结果分析得,该程序功能满足题目要求。
3、调试过程中遇到的问题及解决方法
①当代码编写完成后,编译过程出现了很多小错误,比如语句末尾漏掉分号,使用了某些变量却未定义,但这些问题很快发现并及时纠正;
②在建立广义表的函数中,建立结点后对其data域赋值不完整,一些特殊结点指针域的说明也不完整,导致输出结果有问题。于是回头进一步梳理思路,是细节部分更加严谨,最后修改正确;
是否继续?(是,输入1;否,输入0):”
输入序号“1”,按回车确定,表示继续操作。
页面提示“输入广义表:”
不输入广义表,直接按回车确定,则页面显示如下:
“广义表未建立
是否继续?(是,输入1;否,输入0):”
输入序号“0”,按回车确定,表示结束操作,页面显示如下:
“Press any key to continue”
{
printf("输出结果为:");//提示以下结果为输出的广义表
实验成绩:99
指导教师签名:
批阅日期:2013.11.4
代码:
# include<stdio.h>
# include<stdlib.h>
//——————————————————————————————————————————
typedef struct LNode//广义表结点的类型描述
{
int tag;//tag为结点中的标记域
2、广义表的建立
本程序中利用数组存储所输入的广义表,然后从头到尾扫描数组中的每一个字符根据字符的不同分别执行不同的操作,并用一个存储结点指针的栈辅助完成。在扫描前先申请一个结点作为头结点,也是当前指针所指结点,在广义表的建立的过程中,每次申请一个新结点,需对其进行初始化,即令标记域为0,data域为空。按照本程序的思路,广义表(a,(b,c),())的链式存储结构如下图所示。广义表建立的具体过程见详细设计部分。
若当前结点p的next域不为空,表示不是该层的结束,输出','
将当前结点p的next域所指结点赋给p
}
}
◎若当前结点指针为空,执行以下操作
{
输出')'
出栈,将栈顶元素赋给当前结点p,
若当前结点p的next域不为空,表示不是该层的结束,输出','
将当前结点p的next域所指结点赋给p
}
}
}
四 使用说明、测试分析及结果
本次实验,我很感谢老师和同学对我的指点。通过本次实验,对广义表的存储结构有了更深的认识,对一些细节更加理解,收获了很多。
教师评语:
首先,我强调一下要注意细节,不论是对你而言简单的部分还是复杂的部分,这些都会影响你程序的编译和调试,另外,在充分考虑并设计好程序后在进行编写操作这是一个良好的习惯,这样能够提高你的编程效率,降低出错的可能性,当然,最好的话细分模块是一个比较好的习惯,当然这主要是针对大型程序而言。
一、需求分析
1、输入的形式和输入值的范围:根据提示,输入广义表,按回车结束。
2、输出的形式:输出结果为上一步所输入的广义表。
3、程序所能达到的功能:输入广义表后,该程序可以建立广义表的链式存储结构,之后按照一定的顺序访问结点并输出相应的值,从而完成广义表的输出。
4、测试数据:
输入广义表:((),a,b,((c,(d,()))),((())))
输出广义表的函数:Display(GLNode *G,SeqStack &K)
主函数:main( )
函数的调用关系如下图所示:
三 详细设计
(一)元素类型、结点类型
1、广义表结点的类型描述
typedef struct LNode
{
int tag;//tag为结点中的标记域
char data;//data用于存储广义表中的字母
{
GLNode *p,*q;//p指针指向当前结点,q指针指向新申请的结点
int j;//j用于标记输入的字符在数组中的位置
printf("输入广义表:");//提示输入广义表的
gets(s);
p=G;//令p指向头结点
p->next=NULL;//头结点的next域为空
for(j=0;s[j]!='\0';j++)//进入循环,建立广义表
③更多的问题出现在了输出广义表的函数中,刚开始出现广义表的输出少括号或多括号的情况,这里有一部分原因是建立广义表的函数的问题,两部分同时作的修改。之后又出现输入复杂的广义表时,部分字母不能输出,多重括号的输出也只能输出两个,认真分析后,发现还是对广义表中右括号的处理不够完善,于是在输出时,进一步细化了输出结果的条件,比如对“(a,b)”和“()”这两种形式采取不同的输出条件和输出结果。在不断地查找问题和完善中,最终修改正确。
q->data=NULL;
p->next=q;//当前结点的next域指向新申请的结点
p=q;//令新申请的结点成为当前结点
}
else
{
if(s[j]==')')//若字符为')',执行以下操作
{
p->next=NULL;//令当前结点的next域为空
p=K.pin[K.top];//出栈,令当前结点为栈顶元素
{
GLNode *pin[20];//指针数组,用于存储广义表结点指针
int top;//栈顶指针
}SeqStack;
//——————————————————————————————————————————
void Create(GLNode *G,SeqStack &K,char s[])//建立广义表函数
③将当前结点p的sublist域所指结点赋给p。
④当栈不空时执行以下操作
while(K.top!=-1)
{
◎若当前结点指针p不为空,执行以下操作
{
若当前结点标记域为1,执行以下操作
{
输出'(',并当前结点指针p入栈
将当前结点p的sublist域所指结点赋给p
}
若当前结点标记域为0,执行以下操作
{
若当前结点p的date域存有字母则输出该字母
struct LNode *sublist,*next;//sublist为指向下层的指针,next为指向同一层的指针
}GLNode;
2、顺序栈的类型描述
typedef struct
{
GLNode *pin[20];//指针数组,用于存储广义表结点指针
int top;//栈顶指针
}SeqStack;
《数据结构》实验报告
◎实验题目:广义表的建立与输出
◎实验目的:1、掌握使用Visual C++6.0上机调试程序的基本方法;
2、掌握广义表的存储结构,学会广义表的建立与输出;
3、提高自己分析问题和解决问题的能力,在实践中理解教材上的理论。
◎实验内容:利用链式存储结构建立广义表,然后输出该广义表,在本实验中不使用递归的方法,而是用一个栈存储结点的指针,以此完成实验要求。
K.top--;
}
else//若字符为字母,执行以下操作
{
p->data=s[j];//令当前结点的data域为该字母
p->sublist=NULL;//当前结点的sublist域为空
}
}
}
}
}
//——————————————————————————————————————————
void Display(GLNode *G,SeqStack &K)//输出广义表的函数
3、广义表的输出
在广义表的输出过程中也需利用一个存储结点指针的栈辅助完成,初始时栈为空,广义表输出结束后栈也为空,所以在开始时将头结点入栈,之后根据当前指针所指结点的特性的不同执行不同的操作,以栈空作为广义表输出的结束条件。广义表输出的具体过程见详细设计部分。
4、本程序的基本操作和模块:
建立广义表的函数:Create(GLNode *G,SeqStack &K,char s[])
出栈,将栈顶元素赋给当前结点q
}
◎若字符为字母,执行以下操作
{
令当前结点p的data域为该字母
令当前结点的sublist域为空
}
}
}
3、输出广义表的函数
void Display(GLNode *G,SeqStack &K)
{
①定义表示当前结点的指针p,并令p指向头结点。
②指向头结点的指针p入栈,使栈不空,输出广义表里的第一个左括号'('。