算法与数据结构c语言描述实验指导书.docx
- 文档编号:23536595
- 上传时间:2023-05-18
- 格式:DOCX
- 页数:27
- 大小:248.38KB
算法与数据结构c语言描述实验指导书.docx
《算法与数据结构c语言描述实验指导书.docx》由会员分享,可在线阅读,更多相关《算法与数据结构c语言描述实验指导书.docx(27页珍藏版)》请在冰豆网上搜索。
算法与数据结构c语言描述实验指导书
《数据结构》实验指导书
计算机科学与工程学院
实验一、熟悉实验环境和单向链表……………………….……………………………..………3
实验二、多项式运算………….………..…………………………………………………………14
实验三、顺序栈的编写…...…………………………………………………………..………….17
实验四、栈的使用—括号匹配…………………..………………………………………………18
实验五、循环队列…………………………………………………..………………….…………19
实验六、二叉排序树…………………………………………………..…………………………20
实验七、图……………………………………………………..………………………………….21
实验八、排序…………………………………………………………..…………………………22
实验九、查找…………………………………………………………..…………………………23
实验一熟悉实验环境和单向链表
一、实验目的
熟悉VC6实验环境
掌握单链表的理论,并能根据需要编写相应的代码
二、实验内容
1、VC6编写控制台c程序指南和代码编写的一些规范
使用VC开发c语言程序,首先要熟悉VC的IDE环境。
IDE(IntegratedDevelopmentEnvironment),即集成开发环境。
编译器厂家将程序编辑器、编译程序、连接程序和调试程序集成在一个开发环境中,使得这个开发环境能完成所有的开发工作,这就是IDE。
当启动VC后,就可以看到它所提供的IDE环境。
如何在VC环境中用c语言编程,开发控制台应用程序。
主要的步骤分为:
1.新建项目
2.添加文件到新建的项目中
3.编写代码
4.编译链接生成可执行文件
其中,代码的调试也是一个很重要的过程。
(一)、新建工程
图1
注意,在图1中一定要选择Win32ConsoleApplication,这样才能编写控制台应用程序。
在图1的中的Projectname下面的文本框填写自己工程的名字,在Location中选择工程要存放的硬盘。
填好后,点击OK,进入下一步。
图2
在图2中,默认选择Anemptyproject,保持默认选项,点击Finish。
就建立了一个空白的控制台工程项目。
以后可以往这个空白的项目中添加现有文件(已经编写好的.c或者.h文件),或者是添加新的空白文件(已经编写好的.c或者.h文件),用于在其上编写自己的代码。
二、往工程中添加文件
应注意,刚选择的是新建一个空白的工程,因此,新建的工程中没有任何.c或者.h文件,现在需要往工程中添加代码文件。
在工程已建立的情况下,有两种方法往工程项目中添加代码,一种是添加空白的.c文件和.h文件,然后自己在这些空白的文件中编写代码,另一种是添加现有的.c文件和.h文件。
若要把添加到工程中的.c或者.h文件从工程中删除,只需要在workspace中选中相应的文件,按下键盘上的delete键,就可以了。
不过,注意,此时文件仅仅是被从工程中移除了,还在硬盘中存在,如果要彻底将文件删除,需要在硬盘上文件保存的地方进行删除。
1.添加空白的.c文件和.h文件
选择File菜单项中的New
(1)添加.c文件的方法如下:
图3
在图3的左边选择C++SourceFile,右边给这个文件取名,这里取名为Demo.c。
需要注意的是后缀一定要为.c,如果不填写,则默认为.cpp类型的文件。
(虽然有人说c是c++的子集,但是,二者还是有些区别的,当编译器把c程序认为是c++程序的话,会有些问题。
)填写后,点击OK按钮。
(2)添加.h文件的方法如下:
图4
图4中,选择C/C++HeaderFile,跟上面一样,可以添加头文件。
2.添加现存的.c文件和.h文件
需要在哪个文件夹下添加文件,直接在那个文件夹上点击右键,如图选择,就可以在随后弹出的对话框中选择相应的文件了。
三、VC的IDE界面的简单介绍
下面简单的介绍一下,VC的IDE界面
图5
如图5所示,VC的IDE界面和传统的Windows程序一样,包含有菜单条、工具条和状态条。
除了这些,主界面共分为三大部分,分别是Workspace窗口、工作区和输出窗口。
其中,Workspace窗口在图5的左半部分,包括FileView页面和ClassView页面,若是编写c程序,只涉及到FileView页面。
在FileView页面中,对加入工程中的文件(包括.h和.c文件)进行了组织,分为3个文件夹,其中,SourceFiles中存放的是.c文件,HeaderFiles中存放的是.h文件,ResourceFiles中存放的是资源文件,而这在现在简单的c程序编写中不会涉及到(若是使用win32API,编写windows程序,会涉及到),因此跟我们相关的只有两个文件夹,SourceFiles文件夹和HeaderFiles文件夹,这两个文件夹对源文件做了很好的组织。
如果你愿意或者说是为了满足编程的需要,也可以在其中新建新的文件夹,管理你的代码文件。
工作区,在窗口的右边,在其中能打开多个代码页面,可以方便的对代码进行编辑修改。
输出窗口在窗口的下部,这个窗口在对程序进行编译链接或者进行调试的时候会出现,显示一些信息。
四、编译链接运行程序
对编写好的程序进行编译链接,可以使用菜单项中的Build菜单,也可以使用工具条中的工具。
Build菜单是VC提供的辅助编程的主要菜单,用于对项目进行编译,连接并生成可执行文件。
其中几个子菜单简单介绍如下:
Compile:
编译当前激活的源文件或头文件
Build:
编译并链接当前激活的项目配置
RebuildAll:
对当前激活的项目配置先Clean,再Build
SetActiveConfiguration:
设置哪个项目配置被激活(其中,默认的是生成Debug版本)
工具条如下:
其中,第一个图标是Compile,第二个图标是Build,第三个是stopbuild,第四个是执行程序(如果新修改好的程序没有编译和链接的话,会有提示,先对程序重新编译链接,再执行),第五个是调试,第六个是设置或移除断点。
五、调试程序
调试程序很重要,有很多方法,比如,可以用printf语句输出中间结果进行调试。
VC6中集成了调试器,可以用vc6的调试器设置断点,进行调试,观察中间结果信息。
主要快捷键的解释如下:
F9:
设置断点
F5:
调试运行
F10:
单步执行,遇到函数不进入函数内部
F11:
单步执行,遇到函数进入函数内部
Shift+F11:
跳出函数
熟练运行快捷键,在调试时会感觉很方便。
在调试过程中会有各种窗口,对中间值进行观察,便于进行程序的调试;同时也会有一个调试的工具栏,如果没有出现调试工具栏,则可以用如下方法调出:
另外,注意一点,最好调试结果是输出窗口中显示的信息中警告也为0个,因为编译器在编译程序的时候,有时检查得不是会很准确的或者说也跟设置的警告的级别有关系,有些警告,在运行的时候就可能会产生问题。
因此,最好是编写的程序在编译链接的时候显示的错误和警告都是0个。
附录:
代码编写的一些规范
1.使用头文件
每个c++/c程序通常分为两个文件。
一个文件用于保存程序的声明(declaration),称为头文件。
另一个用于保存程序的实现(implementation),称为定义(definition)文件。
头文件中只存放“声明”而不存放“定义”。
要学会使用头文件,不要把所有的代码都编写到一个.c文件中,虽然在程序短小的时候,这样做也许也是一个不错的选择,但是,当程序的规模稍微大些的时候,应该学会使用头文件,并且不要把所有的代码都集中到一个.c文件中。
使用头文件的原因或作用如下:
(1)通过头文件来调用库功能。
在很多场合,源代码不便或不准向用户公布,只要向用户提供头文件和二进制的库即可。
用户只需要按照头文件中的接口声明来调用库功能,而不必关心接口怎么实现。
编译器会从库中提取相应的代码。
(2)头文件能加强类型安全检查。
如果某个接口被实现或被使用时,其方式与头文件中的声明不一致,编译器就会指出错误,这一简单的规则能大大减轻程序员调试、改错的负担。
在头文件中,为了防止头文件被重复引用,应当用ifndef/define/endif结构产生预处理块。
用#include
用#include“filename.h”格式来引用非标准库的头文件(编译器将从用户的工作目录开始搜索)。
一个头文件结构的例子如下:
头文件结构(graphics.h)
#ifndefGRAPHICS_H//防止graphics.h被重复引用
#defineGRAPHICS_H//其中GRAPHICS_H为预编译器常量
#include
…
#include“myheader.h”//引用非标准库的头文件
…
voidFunction1(…);//全局函数声明
…
structBox//结构声明
{
…
};
#endif
2.程序的版式(可读性)
代码编写出来是给人看的,而不是给机器看的。
编写具有良好的可读性的代码,写上比较好的注释,这样方便自己以后的修改调试,也方便别人的阅读。
有良好的可读性的代码,需要在代码中有适当空行。
代码编写过程中,成对编码原则,也就是说,左右括号是一一对应的,写完左边的括号,最好马上写右边的括号,然后再在两个括号中间填写代码。
另外,内存的分配和释放也都要注意是成对出现的(这里还没有涉及到)。
添加适当的注释,比如函数接口说明,重要的代码段,主要的算法等等。
但是,注释不可以过多。
在VC6中,快速将混乱的代码转换成整齐的代码的方法:
选中需要格式化的代码段,然后按下Alt+F8(或者选择Edit|Advanced|FormatSelection)
3.统一的命名规则
编写程序的时候要注意有一个统一的命名规则。
比如,变量和参数用小写字母开头的单词组合而成;常量全用大写的字母,用下划线分割单词;静态变量加前缀s_(表示static);如果不得已需要全局变量,则使全局变量加前缀g_(表示global)等等。
给函数,变量命名的时候,需要起有意义的名字。
单向链表结点的插入和删除
下面有一个单向链表的部分代码,实现的功能为:
按任意顺序输入几个整数,构造一个排序的线性表,线性表中的元素是降序排列的。
主要函数有3个
插入结点:
通过插入结点的方式构造降序排列的链表
打印链表:
遍历链表中的元素,将其打印出来
删除结点:
根据用户需要删除链表中的结点
其中,插入结点函数,主函数给出,需要补充完整删除结点和打印链表函数,能实现删除链表中结点的功能。
注意:
(1)这里的链式存储结构的线性表中,头结点head也是分配了空间的
(2)如果全部的代码自己能编写出来,更好(自己编写代码的时候,可以给头指针不分配结点空间,仅仅是一个指针)
编写链式存储结构的线性表时候需要注意下面几点:
(1)链表的每个节点都要分配空间
(2)编写单向链表的时候,一定有一个头结点,而因为有这个头指针,根据是否为头指针分配一个实在的结点空间,有两种方法实现后续的链表结点的插入删除遍历等操作。
相对来说,给头指针分配一个实实在在的结点空间(这样这个结点的数据区域会被浪费)的做法利于后续的结点插入和删除操作的实现。
下面为部分代码,可以复制到VC环境中读懂后,编写删除链表结点的函数:
linckList.c
/*
降序链表的插入,删除,打印
*/
#include
#include
structtagNode
{
intdata;
structtagNode*pNext;
};
typedefstructtagNode*pNode;
//将结点插入到链表的适当位置,这是一个降序排列的链表
//
voidinsertList(pNodehead,//链表头结点
pNodepnode)//要插入的结点
{
pNodepPri=head;
while(pPri->pNext!
=NULL)
{
if(pPri->pNext->data
{
pnode->pNext=pPri->pNext;
pPri->pNext=pnode;
break;
}
pPri=pPri->pNext;
}
if(pPri->pNext==NULL)//如果要插入的结点最小
{
pPri->pNext=pnode;
}
}
//输出链表
voidprintLinkedList(pNodehead)
{
pNodetemp=head->pNext;
while(temp!
=NULL)
{
printf("%d",temp->data);
temp=temp->pNext;
}
}
//从链表中删除结点
voiddelformList(pNodehead,intdata)
{
pNodetemp=head->pNext;
pNodepPri=head;
while(temp!
=NULL)
{
if(temp->data==data)
{
pPri->pNext=temp->pNext;
free(temp);
break;
}
pPri=temp;
temp=temp->pNext;
}
}
voidmain()
{
pNodehead=(pNode)malloc(sizeof(structtagNode));//给头指针分配空间
pNodepTemp=NULL;
inttemp;
head->pNext=NULL;//比较好的习惯就是分配好空间,马上赋值
printf("请输入要放入链表中的数据,以-1结尾:
");
//读入数据,以-1结尾,把数据插入链表中
scanf("%d",&temp);
while(temp!
=-1)
{
pTemp=(pNode)malloc(sizeof(structtagNode));
pTemp->data=temp;
pTemp->pNext=NULL;
insertList(head,pTemp);
scanf("%d",&temp);
}
printf("降序排列的链表为:
\n");
printLinkedList(head);
printf("\n");
//下面的代码当删除函数编写成功后,可以取消注释,让其执行,主要是调用函数实现链表结点的删除
//printf("请输入要删除数,以-1结尾:
");
//scanf("%d",&temp);
//while(temp!
=-1)
//{
//delformList(head,temp);
//scanf("%d",&temp);
//}
//printf("删除节点后,链表中剩余数据为:
");
//printLinkedList(head);
//printf("\n");
}
实验二多项式运算
一、实验目的
1、需要从简单的一个文件的C程序中转变过来,知道一个程序的哪些部分要放到.c文件中,哪些部分放到.h文件中,能清晰的组织多个文件进行编译链接,即学会多文件项目的组织
2、初步掌握在VC环境中进行代码的调试
3、掌握一元稀疏多项式的链式存储结构及其加法、减法运算的实现,进一步熟悉链表的插入、删除操作
二、实验内容
问题描述:
设计一个一元稀疏多项式简单的加减法计算器
实现要求:
一元稀疏多项式简单计算器的基本功能是:
(1)输入并建立多项式:
;
(2)输出多项式
(3)多项式A和B相加,建立多项式C=A+B,并输出相加的结果多项式C
(4)多项式A和B相减,建立多项式C=A-B,并输出相加的结果多项式D
方法说明:
(1)多项式的输入与存储
用带表头结点的单链表存储多项式,链表中的每个节点分别存储多项式各项的系数和指数,即每从键盘输入多项式的一对数(系数,指数),可对应建立链表的一个结点。
每个节点的结构为:
建立两个链表,其中pa和pb分别为它们的头指针:
Pa
pb
结果链表
Pa(或者是Pc)
Pc
(2)多项式数据类型的定义
structtagNode
{
floatcoef;
intexp;
structtagNode*next;
};
typedefstructtagNodeNode;
typedefstructtagNode*pNode;
(3)主要算法
①创建两个链表,分别存放多项式1和多项式2,这两个链表中的节点是按指数降序或者升序排列的
②多项式相加或相减,下面给出多项式相加的部分实现
/*
下面的函数实现两个多项式的相加,要相加的链表分别由pa和pb指向(其中,pa,pb都是分配了空间的头结点)。
相加的结果直接由pa指向的链表保存,即使在pa链表中添加或删除(当系数因为相加为0的情况下)一些结点,构成结果。
这里要相加的链表中指数都是按从小到大的顺序排列好了的,是升序链表。
*/
voidadd_poly(Node*pa,Node*pb)
{
Node*p=pa->pNext;//链表1,将来的结果也放在此
Node*q=pb->pNext;//链表2
Node*pre=pa;
Node*u;//临时用
floatx;
while(p!
=NULL&&q!
=NULL)//当两个链表都不为空
{
if(p->exp
{
pre=p;
p=p->pNext;//p指向要比较的下一个结点。
pre指向的是结果链表的最后一个结点。
}
elseif(p->exp==q->exp)//假如链表1和链表2的指数相等,就要系数相加
{
x=p->coef+q->coef;
if(x!
=0)//相加后的系数不为0,有必要保留一个结点就可以了
{
p->coef=x;
pre=p;
}
else//如果相加后,系数不是0,不需要保留任何一个结点,在这里删除链表1的结点,下面删除链表2的结点
{
pre->pNext=p->pNext;//保持链表1的连续性
free(p);
}
p=pre->pNext;//p指向要比较的下一个结点
//下面的代码是进行链表2结点的删除工作,因为指数相等,仅仅需要保留一个结点就可以了
//而结果直接保存在链表1中,所以,删除链表2的结点。
u=q;
q=q->pNext;
free(u);
}
else//如果链表2的当前节点指数小,那么要把链表2的当前节点加入到结果链表中(即是链表1)
{//相当于把结点插入到链表1中,用u作为临时变量,保存链表2的下一个当前节点的位置。
u=q->pNext;
q->pNext=p;
pre->pNext=q;
pre=q;
q=u;
}
}
if(q)//如果链表2比链表1长,那么需要把链表2多余的部分加入结果链表中。
链表1比链表2长,则什么都不用做。
{
pre->pNext=q;
}
free(pb);
}
③输出结果多项式
实验三顺序栈的编写
一、实验目的
掌握顺序栈的编写和实现,并能用自己实现的栈实现相应的算法
二、实验内容
XX文库-让每个人平等地提升自我1.自己实现一个顺序栈(栈的成员函数至少必须包括①压栈②出栈③取栈顶元素④判断栈是否为空)
XX文库-让每个人平等地提升自我XX文库-让每个人平等地提升自我2.编写程序,实现功能为:
输入5个整数,然后将这些整数按与输入时相反的顺序输出。
注意:
(1)栈的结构为
typedefstructtagMyStack
{
intarray[MAX_NUM];//栈
intstackNum;//栈里面的元素个数
}myStack;
(2)程序编写的时候,在参数传递的时候要注意,如果改变了输入参数的值,那么要用指针
实验四栈的使用—括号匹配
一、实验目的
通过一个小程序,掌握和了解栈的使用
二、实验内容
从键盘上输入一算术表达式检验该算术表达式中括号是否配对
提示:
(1)配对的算术表达式中左右括号的数目应相等
例如:
表达式(a+b))和a+b)中的括号不配对
(2)对的算术表达式中每一个括号都一定有一个右括号与之匹配
例如:
表达式)a+b(+c和(b+a))+(c+d也属于不配对的情况
算法提示:
括号配对检查的原则是:
对表达式从左向右扫描。
当遇到左括号时,左括号入栈;而遇到右括号时,首先将栈中的栈顶元素弹出栈,再比较弹出元素是否与右括号匹配,如果两者匹配,则操作继续;否则,检查出错,打印“no”,并停止操作。
当表达式全部扫描完后,如果栈为空,说明括号作用层次嵌套正确,打印“yes”,并停止操作。
方式是先创建一个存放左括号的空栈,并将“#”作为栈底元素。
顺序扫描表达式,当遇到非括号时,继续扫描,遇到“(”时,进栈,而遇到“)”时,与栈等元素比较,如果括号匹配,栈顶元素退栈,继续扫描表达式,否则,报错退出。
这个算法实现中,栈的部分可以直接使用上次实验中自己编写好的栈。
不过,如果使用顺序栈,要明白,顺序栈中的元素个数是有限的。
而且要注意,如果使用的话,需要把栈里面存放数据的类型修改为字符型
实验五循环队列
一、实验目的
掌握循环队列的编写和实现,并能用自己实现的队列实现相应的算法
二、实验内容
1.自己实现一个循环队列(队列的成员函数至少必须包括①进队列②出队列③取队首元素值④判断队列是否为空)
2.编写程序,应用队列实现下述题目描述功能(下面包括题目的描述和说明):
设有两个队列A和B,队列A中按次序存放五个大写字母,分别为A,B,C,D,E;队列B中按次序存放五个小写字母,分别为a,b,c,d,e。
要求每次都从A队列队头取出一个元素,从B队列队头取出一个元素,并列输出这取出的两个元素,直到两个队列为空为止。
使得最后输出为:
AaBbCcDdEe
注意:
(1)队列的结构为
#defineMAX_NUM10
typedefstructtagMyQueue
{
chararray[MAX_NUM];//队列
//这里通过浪费一个空间,来区别队列空还是满
//当front==rear时,队列空
intfront;//约定头指针指示队列头元素的前一个位置,注意这是
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 算法 数据结构 语言 描述 实验 指导书