计算机实验心得体会(精选10篇)
本次实验主要任务是学会计算机的拆机、组装和安装操作系统,通过理论与实践相结合,进一步加深我们的理论知识。通过学习了计算机组装,我了解了计算机方面的一些基础知识,包括计算机的发展和系统组成。也了解到了CPU,主板,内存,外存和外部设备等配件的基本结构。还学到了相关方面的工作原理...我们还学了微机组装,CMOS设置和硬盘的分区及格式化。操作系统的安装,驱动程序的安装和常用软件的安装。原来在计算机方面不是很懂的我,开始渐渐地更加深入地认识它了。这样我也就能更好的利用它了,这个一直在我身边陪伴我的朋友。虽然在个别方面我们已经会了,不过我们很高兴能够这么全面,这么系统化的了解到,这对我们受益非浅!这辈子也许都要与计算机打交道了,学习计算机组装充实了我们的知识,能够让我们更好的利用它。
这次学习了计算机组装实验,我最大的收获就是学会了如何把各个部件安插在正确的位置,能够自主独立组装一台计算机,还有学会了如何设置BIOS,设置第一启动项,如何分区等,如何用光盘安装操作系统,也向老师请教,学会了如何用U盘启动PE来安装操作系统,这些都是在课本上学不到的,或者就是空有理论知识,却没有实践能力和经验,对平常计算机遇到一些问题都摆弄很久。通过这次实验,让我有机会理论和实践相结合,发现了以往没注意的或者没有遇到的问题,并得到一一解决,收获颇丰!
“纸上得来终觉浅,绝知此事要躬行!”在短暂的学习过程中,让我深深的感觉到自己在实际运用中的专业知识的匮乏。让我真正领悟到“学无止境”的含义。在进行实训的过程中,我真正学到了计算机教科书上所没有或者真正用到了课本上的知识,这样,既巩固了旧知识,又掌握了新知识。这次实训让我学到的东西太多,使我受益非浅,不过,虽然辛苦了点,但能让我学到不同的东西,我心里还是高兴的。人非生而知之,要学得知识,一靠学习,二靠实践。没有实践,学习就是无源之水,无本之木。
(1)知识点在专业基础课程中具有代表性。
应用电子技术专业基础类课程在各大高校中开设的情况大同小异,数字电子技术基础和模拟电子技术基础两门课程是必需的。一般所选用的项目中数字电子技术或者是模拟电子技术基础的知识点应该体现得比较清晰,容易分离出知识点进行实际应用讲解,这样该项目可以作为专业基础课程的应用实例。
本案例中(如图1)的集成计数器芯片应用、集成门电路应用、集成数字电位器应用、上拉/下拉电阻应用、RS触发器应用、555定时器应用、三极管的开关作用等,都是非常典型的知识点,在了解电路作用的前提下,进行局部电路分析可以帮助学生进行知识点巩固学习和灵活运用。
(2)复杂度适中,作为专业技能训练类课程的入门项目。
应用电子技术专业技能训练类课程在各大高校中开设的情况也是大同小异,电子设计自动化(简称EDA)课程是必需的,EDA课程有课分为板级设计类的印制电路板(PCB)设计和芯片级设计类的可编程逻辑门阵列(FPGA)两门课程。
对于这两门课程,如果是单讲软件的使用操作,那就失去了其本身的意义,在这两门课程中,学会使用计算机辅助设计软件是一定的,并且要体会板级电路设计和芯片级电路设计的区别和实际应用价值,更重要的是要能够自己设计相应的电路,完成设计要求。
要利用计算机辅助设计进行板级或者芯片级的电路设计,熟悉电路原理,掌握设计关键是至关重要的,对于初学者而言,如果课程开始便选用未见过的电路,则很难理解,更加谈不上进一步的设计。但是,如果教学所使用的项目中各单元电路部分是在先修的专业基础类课程中作为实际案例,在不同的场合和章节中已经分析过的,那么在进一步的设计课程中,学生将会很好地衔接和过渡。例如电路图的模块化设计,数字功能模块的设计都需要对单元电路原理非常熟悉才能进行电路的合理划分和硬件描述语言程序的设计。
在先修专业基础类课程中所选用的项目的复杂度应该适中,在计算机辅助设计课程中,作为入门项目,甚至是提高项目。
本案例作为印制电路板设计入门项目,属于典型的数字电路印制电路设计,可以将设计的一般要求融入其中,在原理已经基本明了的情况下,引导学生进行电路的进一步设计将会事半功倍,而且比较容易建立学生学习的信心。比如,布局设计中输入/输出接口、按键、信号产生电路等关键部件的设计技巧;布线设计中电源线、接地线、时钟脉冲信号线、被控制信号线等的参数设计和走线技巧。
随后在专业技能训练类课程的提高项目和综合项目中逐验为基础的学科,动物实验难度大,学生的实验成功率很难达到百分之百。将计算机模拟实验引入生理学实验课教学,既可以帮助学生更好地理解和掌握生理学理论知识,培养学生的观察、思维能力,又可以真实、动态地再现生理学多种实验过程,节约实验经费。我们对三年来我校教研室将计算机模拟实验应用于生理学实验课教学的情况进行了分析、总结。
1. 计算机模拟实验激发了学生的学习兴趣
计算机模拟实验是利用计算机及其仿真软件来模拟实验的环境与过程,让学生通过计算机来做实验,以达到实验目的渐地增加训练强度和设计难度,达到更高的水平。
(3)可移植性好作为核心类课程的设计原型。
应用电子技术专业核心类课程一般都包括单片机设计、综合电路设计等设计类课程。运用数字控制类芯片可以使电路智能化,功能更加强大,而且电路却非常简单。例如在本案例中的按键消抖动是采用门电路构成的RS触发器实现,其可以在单片机中软件消抖动;本案例中的步进控制需要为数字电位器输入单脉冲或者是连续的十个脉冲,使用单片机程序可以非常容易地实现而摆脱复杂的硬件电路。
类比设计可以将抽象的枯燥单片机功能讲解用实际效果来体现,直观的学习比抽象的学习更受学生欢迎,而且学习的效果会更好。
(4)易调试,观察现象明显。
在高职类院校的应用电子技术专业中,经常会包括一些安装调试类课程。同样,在入门项目中,教师采用先修课程中已经出现过的项目原理,可以在课程开始时,借助项目原理已经比较清晰的前提,将教学重点放在调试技巧、仪器使用技巧、数据记录分析技巧方面,在后续的提高项目和综合项目中再逐渐地增加电路的复杂程度和调试难度,达到更高的水平。
3.结语
采用衔接式的项目内容引导教学,在专业课程体系中,构建一个甚至是多个产品的设计生产全过程,有助于形成真正的以产品为对象的教学体系;对于接受引导学习的学生而言,可有效地实现课程间的平滑过渡,每次新阶段的学习都能很快上手,并逐渐学习和掌握新的知识和技能,最终形成完整的知识体系。对于校企合作而言,订单式培养是校企合作的一项重要内容,企业可以提供自身的比较有代表性的产品作为教学的对象,在分析、设计和调试中实现针对性的培养,实现企业实践与学校教育的良好对接。
参考文献:
[1]林汉.应用电子专业课程体系改革初探[J].湛江师范学院学报,2001,(03).
[2]张源峰.高职应用电子专业模块化课程体系设计与教学实施[J].闽西职业技术学院学报,2006.6.
[3]李宗宝.关于应用电子技术专业课程体系改革的实践[J].职业教育研究,2007,(3).
[4]姜大源,吴全全.当代德国职业教育主流教学思想研究———理论、实践与创新[M].北京:清华大学出版社,2007,(4)
[5]欧盟ASIA-LINK项目“关于课程开发的课程设计”课题组.职业教育与培训———学习领域课程开发手册[M].北京高等教育出版社,2007,(6).
《内科护理学》教学中存在的问题及对策探讨
杨茜
(泸州医学院护理学院,四川泸州
摘要:《内科护理学》是护理专业的核心职业能力课,是关于认识疾病及其防治﹑护理病人﹑促进康复﹑增进健康的重要课程,以培养高素质的护理技术应用型人才为目的。本文分析了《内科护理学》教学现状并对提高教学质量的因素进行了探讨。
关键词:内科护理学教学质量教学模式
1. 目前《内科护理学》教学中存在的问题
1.1 护理教学模式守旧。
随着医学模式的转变,护理服务从以疾病为中心转向的应用系统[1]。教研室每学期在学生上生理实验课之前,会对每个小班都安排一次计算机模拟实验。利用计算机模拟实验指导学生在实验课前进行预习,并以骨骼肌的单收缩和复合收缩、家兔呼吸运动的调节这两个实验为例进行重点讲解,讲述生理实验中用到的实验动物与基本的操作方法,然后模拟实验全过程。这样就让学生对生理实验的基本操作有了基本了解,避免在以后的具体操作中出现无从下手,甚至晕头转向的局面,从而将实验操作变难为易。同时,模拟实验演示的整个实验过程是教师备课时、操作时最为成功的录像,并配有录音讲解和局部放大,对学生具有很强的吸引力,激发了学生持久的学习兴趣和学习热情,有助于加深对课程内容的理解,提高学习效率。
2.计算机模拟实验经济、安全可靠
实验是对学生进行创造意识训练和科学的学习方法训练的有效途径,实验本身就是一种最基本的科学研究方法。生理学是一门实验性科学,它的所有知识都来自临床实践和实验研究[2]。所以,在生理学教学过程中我们必须开展实验教学,但传统的生理学实验教学存在诸多不足。比如,受到学时数、实验仪器、经费、环境污染等因素的影响,导致很多生理实验在现有的条件下难以对本科生开展,学生的实验技能和视野难以得到全面提升。因此,我们在重视传统生理学实验课教学的同时,拓展计算机模拟实验,大大扩展了学生的视野范围。模拟实验能让学生去探索那些价格比较昂贵、实验动物缺乏、动物处理时间长或者在现实实验教学条件下无法开展的实验,如离体心肌细胞动作电位、颈动脉窦压力感受性反射等实验。模拟实验也相对比较直观,能够重复再现,从而加深了学生对实验的印象,使教学更形象、生动,不仅能达到实验的基本目的要求,而且能节约实验经费,达到事半功倍的效果[3]。
3.计算机模拟实验提高了学生的实际动手能力
大多数生理教师在实验课教学时会遇到这样的问题,即加强大学生实验基本操作技能培养和现实实验条件之间的矛盾。实验技能是通过反复练习而获得的一种动手操作能力。而生理实验课的学时数是有限的,所以在实验课上没有足够的时间让学生反复练习基本的操作技能。在实验课上经常看到有些同学存在一边看书一边做实验、损坏仪器、浪费实验动物、操作不规范等问题。由于学生对生理实验的基本操作技能训练不够,实验前又没有及时预习,从而导致不能对实验进行合理的安排,实验进程缓慢,往往下课时间已到,实验还没有完成。我们发现在广泛开展计算机模拟实验的基础上,学生再动手进行真实的动物实验操作,从动物的麻醉到手术的进行,如捣毁蟾蜍的脑和脊髓、切开家兔颈部皮肤、迷走神经分离、
李雨昕
以人的健康为中心,护理工作方式也从被动执行医嘱转向主动地为护理对象提供全面整体的护理,这就要求传统的护理教育模式应该发展成为对人的身体、心理、社会适应与文化和精神进行全面评估,实施身心整体护理的现代护理教育模式[1]。
1.2教学手段有待改革。
《内科护理学》理论性强,知识面涵盖广,实践性要求高,传统单纯的课堂讲授常使学生感到内容抽象难以理解。
1.3部分教学内容落后。
我国的护理教育无法满足不断发展的临床实践对护理教止血、气管插管等,进行得都很顺利。实践证明,在进行计算机模拟实验预习之后,再进行真实的生理实验,学生更能明确实验目的、实验内容,思路更清晰,更能把握知识要领,实验成功率明显提高。另外,模拟实验还可以为学生自觉、独立地进行实验打好基础,并使他们逐步养成实验准备的习惯,强化了实验准备意识。
4. 计算机模拟实验不能完全替代学生的动手实验
计算机模拟实验虽然非常逼真,能收到意想不到的效果,但只是“水中月、镜中花”,实验者缺乏在做实验过程中亲身经历的体验。同时,生理学实验也是培养学生学习兴趣的重要途径,是验证并复现生理学理论知识的重要方法。如果过多地用计算机来模拟动物实验,生理学实验在教学中应起的作用就无法充分实现。因为计算机不能代替一切,模拟实验所做的一切都是虚拟的。而且计算机的模拟实验都受程序控制,是一种理想化的模式,实验只会成功不会失败,使学生没有机会体验实验失败,也没有机会去思考并分析实验失败的原因。所以,凡是能让学生做的实验,必须让他们亲自动手操作,这样才能够使学生的实验能力、动手能力、分析问题、解决问题的能力真正得以提高[3]。
5. 结语
实验是学生获取生理学知识的重要途径,实验教学是生理学教学的重要组成部分[4]。教师通过计算机模拟实验可以完成其中的演示性和验证性实验的相关教学内容,能够引起学生的重视。教师通过模拟实验指导学生进行课前预习,让学生提前亲临“实验现场”,可以提高实际实验操作时的成功率,增强学生对学习理论课的兴趣,有助于加深对课程内容的理解。但是,计算机模拟实验绝不能代替生理学传统的经典实验,学生需要真正到实验室中去锻炼动手、动脑、分析问题和解决问题的能力,培养实事求是、一丝不苟的科研精神。实践证明,把计算机模拟实验和传统的生理学实验有机结合起来,既提高了学生的学习兴趣和理论研究能力,又锻炼了学生的实际动手操作能力,有利于生理学实验教学质量的提高,可以取得良好的实验教学效果。
摘要:计算机模拟实验在生理学实验教学中的应用日趋广泛,学生在计算机上进行模拟实验,可以提高学习兴趣与实际动手操作能力,加深对课程内容的理解。教师把模拟实验和传统的生理学实验有机结合起来,有助于提高生理学实验教学质量。
关键词:计算机模拟实验,生理学实验教学,应用
参考文献
[1]林桂平,向秋玲,王淑珍等.虚拟实验及其在生理学教学中的应用[J].医学教育探索,2007,6(10):948-955.
[2]朱大年.生理学[M].北京:人民卫生出版社,2008.
[3]刘伟华.也谈计算机模拟实验在生理学教学中的应用与体会[J].铜陵职业技术学院学报,2009,(2):90-91.
【关键词】公共计算机实验任务设计测评方法
笔者从多年的教学中总结出“任务测评”实验模式,能够较好的提高计算机上机实验的质量与效率,提高学生对计算机知识的掌握和应用。
1设计“任务”
1.1“任务”要明确
在设计“任务”时,要注意学生的特点与知识接受能力的差异,充分考虑学生的现有文化知识、认知能力和兴趣等。在设计的过程中,要始终从学生的角度考虑,根据学生的实际水平来设计每一个模块,针对不同程度的学生来设计不同层次的练习,也就是说要“任务”要有层次感。在“文字处理”时,我就发现有的学生在中学时就已经学过一些相关知识了。这一章共8小节,如果按部就班地从第一节开始这样顺序学习,就会造成一些学生上课时不想听,上机时无事可干。因此在设计“任务”时,就要针对不同程度的学生来设计不同层次的练习,设计出不同的“子任务”,精心组织教学内容,使学生能顺利地完成“任务”。具体办法是:对于一些从没有学过的学生,我就要求他们先学会简单基本的文字处理方法,我布置的“任务”相对容易些,让他们先学会做一个课程表,通过制作课程表这个任务,学生就掌握了如何进行汉字输入、如何创建和编辑文档等一系列的简单知识;对于那些学过一些基本知识的学生,我布置的“任务”难度就稍微大一些,要求学生设计出一张自己的报纸,打印出来,然后还进行年级评比。通过这样的活动,大大激发了学生的兴致和想象力,这一章节的学习任务也就轻松完成。
1.2“任务”适应教学环境
教师在教学过程中要不断地用“任务”来引导学生自学。在学生学习过程中,要充分发挥多媒体计算机综合处理图形、图像、声音、文字等多种信息的功能,设置特定的情境,创设良好的学习氛围。如果有了这样一个良好的教学环境,那么学生在这种愉悦的环境中,便会自觉自愿地学习,主动地完成学习“任务”。在进行《网页制作》实验时,要求学生掌握基本的制作网页的方法。为了创设一个良好的教学环境,在讲课之前,教师就要搜集一些好的网页给学生看。在网页中不仅要有好的文字内容,还要有优美的学生爱听的背景音乐,以及一些好看的动画效果。这样的网页在教学过程中演示,学生会立即表现出兴趣。学生有兴趣学习后,教师就要安排好每一个“子任务”,用一个个“子任务”来引导学生一步一步地学习网页设计。具体这一章的“任务”,可以分为让学生完成制作一个简单网页、制作一个框架网页和制作一个动态网页。在学生制作网页过程中,教师要不断鼓励学生自己看教材,多看一些别人设计好的优秀网页,从易到难地学习。特别是在学生自己动手上机实践时,教师要注重加强学生的自学能力,在旁起一个“辅导员”的作用,给学生答疑,而不是手把手地教。
1.3“任务”要调动学生积极性
从能力培养的角度看,教师要注重调动学生的积极性,培养他们的创新精神和合作意识。在教学过程中,要引导学生积极参与,以此来提高学生上课时的注意力,从而提高学习的效率。
2实验效果的测评
2.1测评理念
2.1.1能够根据任务需求,熟练地使用文字处理、图表处理等工具软件加工信息,表达意图;选择恰当的工具软件处理多媒体信息,呈现主题,表达创意。例如可以使用多媒体素材加工软件、多媒体著作软件、网页制作软件等处理多媒体信息,制作自己的作品。
2.1.2能合乎规范地使用网络等媒介发布信息、表达思想。只有清晰表达的信息,才能使信息接受者明晰所接受的信息蕴含的意义,这样才能使信息有效地在网络上传递,更有利于信息的共享。
2.1.3能选择恰切的媒介来表达信息。信息技术不仅为学生提供了丰富的资源,它还为学生提供了丰富的认知工具以及信息创作与表达的工具。因而学生必须能从繁杂的工具中挑选出最恰切的媒体工具来表达自己的观点与思想。这主要体现在他们对各种工具的信息表现特性与将要表达的信息的特性的深切理解基础之上,同时,还涉及个体对美的感知能力与理解能力。
这一方面能力的评价可以依据学生的作品(包括电子作品和其他形式的作品)来进行。
2.2测评方法
2.2.1分散测评
一般情况下,教师要在实验课时内要完成全部学生的实验测评是不可能的,故此,必须提前下达“任务”,在学生完成“任务”的过程中,注意观察和指导学生,并与学生的学习态度和学习的主导性及完成任务情况相结合,给出评测成绩,特别是提前较早完成“任务”的学生,主要面向学习较好的学生。
2.2.1集中测评
教师要在实验课结束前十分钟对完成和基本完成“任务”的学生进行集中测评,主要依据“任务”完成的知识点给出成绩。
2.2.3网络测评
任务测评的过程穿插在学生完成任务的过程,以突出知识点为主题,以学生的作品为基础进行测评,起到鼓励学生相互学习,完善与提高完成自己的任务,培养学生协作精神。
总之,在“任务测评”实验模式中,任务的是基础,测评是手段,只有“任务”对部分学生就驱而不动,测评特别能够督促那些学习自觉性较差的学生,测评也起到鼓励鞭策的作用,使学生较好的掌握知识点,提高实验教学的质量和效率,提高计算机知识的应用能力和水平。
【参考文献】
[1]郑世珏. 计算机技术教学方法概论[M]. 清华大学出版社,2011.
通过理论课学习了解到计算机网络是当今计算机科学与技术学科中发展最为迅速的技术之一,也是计算机应用中一个空前活跃的领域。如果说广域网的作用是扩大了信息社会资源共享的广度,城域网扩大了用户接入Internet的范围,局域网扩大了信息资源共享的深度,个人区域网络增强了人类共享资源的灵活性,那么物联网是在Internet技术的基础上,利用RFID和各种感知技术自动获取物理世界的信息,构建世界上人与人、人与物、物与物的各种智能信息系统。今后除了计算机,各种智能手机、PDA、传感器、射频标签与移动数字终端设备都会连接到网络之中。随着物联网技术与产业的发展,计算机网络也面临着一个快速发展的局面。
计算机网络是将地理位置不同,且有独立功能的多个计算机系统利用通信设备和线路互相连接起来,且以功能完善的网络软件(包括网络通信协议、网络操作系统等)实现网络资源共享的系统。
通过半学期的实验课学习我学到了以下内容: 实验一:认识packet tracer 软件。Packet Tracer是Cisco 公司针对CCNA认证开发的一个用来设计、配置和故障排除网络的模拟软件。此次试验中要求我们学会安装Packer Tracer,并且利用一台型号为2960的交换机将2台pc机互连组建一个小型局域网;分别设置pc机的ip地址;最后验证pc机间可以互通。
实验二:交换机的基本配置与管理,此实验利用一台型号为2960交换机与一台pc机用配置线console链接。Switch>enable(进入特权模式),Switch(config)# interface fastethernet0/1(进人接口fastethernet0/1的配置模式),Switch(config-if)#speed ?(查看speed命令的子命令),Switch(config-if)# speed 100设置该端口的速度为100Mb/s),Switch(config-if)# duplex full(设置该端口为全双工),Switch# show running-config(显示当前运行的配置),学会了基本的配置语句。
实验三:交换机TELNET远程登录配置,目的是掌握交换机命令行各种操作模式的区别,以及模式之间的切换掌握交换机的全局基本配置掌握交换机端口的常用基本配置参数查看交换机系统和配置信息和当前交换机的工作状态。首先进行交换机配置;然后配置进入特权模式的登录密码Switch(config)# enable password123456;然后配置telnet远程登录密码:Switch(config)#line vty 0 4(进入线程配置模式),Switch config-line)#password 456(配置Telnet的密码)Switch(config-line)#login(启用Telnet的用户名密码验证)。
实验四:交换机VLAN,此次试验包括创建VLAN和划分VLAN,实验目的在于学会
实验五:利用三层交换机实现VLAN间不同的配置。利用三层交换机的路由功能,通过识别数据包的IP地址,查找路由表进行转发。三层交换机利用直连路可以实现不同的VLAN 之间的访问。三层交换机给接口配置IP地址采用SVI(交换虚拟接口)的方式实现VLAN 间互连。SVI是指为交换机中的VLAN 创建虚拟接口,并且配置IP地址。
实验六:快速生成树配置。快速生成树在生成树协议的基础上增加了两种端口角色:替换端口和备份端口,分别做为根端口和指定端口的冗余端口。当根端口或指定端口出现故障时,冗余端口不需要经过50秒的收敛时间,可以直接切换到替换端口或备份端口,从而实现RSTP协议小于1秒的快速收敛。实验七:路由器的基本配置。其目的在于掌握路由器的配置途径与配置方法,熟练掌路由器的常规则配置操作与相关的配置命令。此次实验利用一台2811路由器和一台pc 机由配置线和交叉线链接。
PC实验
姓名:孙坚
学号:134173733
班级:13计算机
日期:2015.5.15
一.实验要求:利用CPTH 实验仪上的K16..K23 开关做为DBUS 的数据,其它开关做为控制信号,实现程序计数器PC的写入及加1 功能。
二.实验目的:
1、了解模型机中程序计数器PC的工作原理及其控制方法。
2、了解程序执行过程中顺序和跳转指令的实现方法。
三.实验电路:PC 是由两片74HC161构成的八位带预置记数器,预置数据来自数据总线。记数器的输出通过74HC245(PCOE)送到地址总线。PC 值还可以通过74HC245(PCOE_D)送回数据总线。
PC 原理图
在CPTH 中,PC+1 由PCOE 取反产生。当RST = 0 时,PC 记数器被清0 当LDPC = 0 时,在CK的上升沿,预置数据被打入PC记数器 当PC+1 = 1 时,在CK的上升沿,PC记数器加一 当PCOE = 0 时,PC值送地址总线
PC打入控制原理图
PC 打入控制电路由一片74HC151 八选一构成(isp1016实现)。
当ELP=1 时,LDPC=1,不允许PC被预置 当ELP=0 时,LDPC 由IR3,IR2,Cy,Z确定 当IR3 IR2 = 1 X 时,LDPC=0,PC 被预置
当IR3 IR2 = 0 0 时,LDPC=非Cy,当Cy=1时,PC 被预置 当IR3 IR2 = 0 1 时,LDPC=非Z,当Z=1 时,PC 被预置 连接线表
四.实验数据及步骤:
实验1:PC 加一实验 置控制信号为:
按一次STEP脉冲键,CK产生一个上升沿,数据PC 被加一。
实验2:PC 打入实验
二进制开关K23-K16用于DBUS[7:0]的数据输入,置数据12H
置控制信号为:
每置控制信号后,按一下STEP键,观察PC的变化。
五.心得体会:
实验目的:了解计算机绘图的基本原理;熟悉AutoCAD的界面、环境设置。掌握管理图形的方法,掌握工具栏中各按钮的功能及图层的设置、掌握确定点的位置的方法。
实验方式:学生独立上机操作
实验内容:(见书第1、2、3章,写出具体操作步骤,包括图)
实验二常用绘图命令练习
实验目的:掌握各绘图命令的操作方法,特别是各命令中不同选项的功能并正确运用,能应用命令精确绘制平面图形。
实验方式:学生独立上机操作
实验内容:(见书第5章,写出具体操作步骤,包括图)
实验三常用编辑命令练习
实验目的:掌握各种编辑命令的操作方法并能熟练应用,能应用编辑命令生成各种复杂的平面图形。
实验方式:学生独立上机操作
实验内容:(见书第6章,写出具体操作步骤,包括图)
实验四零件图绘制
实验目的:熟练应用绘图和编辑命令绘制零件图;掌握零件图中文字标注、尺寸标注及粗糙度符号标注的方法及块的操作。
实验方式:学生独立上机操作
实验内容:(见书第7、8、9、10章,写出具体操作步骤,包括图)
实验五装配图绘制
实验目的:熟练应用绘图和编辑命令绘制装配图;掌握装配图中尺寸和序号标注的方法及明细表的填写。
实验方式:学生独立上机操作
实验内容:(见书第12章,写出具体操作步骤,包括图)
实验六三维图形绘制
实验目的:熟练掌握三维作图和实体编辑命令,绘制形体,掌握三维造型的方法与技巧。
实验方式:学生独立上机操作
本文对计算机数学实验的必要性和其基本原则进行了简单的分析。针对我国目前计算机实验课的开展和应用中存在的一些问题,提出了一些具有针对性的改进措施,如增强计算机数学教师的实验意识、不断提高教师队伍的综合素质、设计合理的循序渐渐的教学环节以及加强学校的硬件设施等。
1 计算机数学实验的必要性
由于计算机数学充分利用了计算机科学中编译理论、容错诊断、操作系统、逻辑设计、数据结构、机器定理证明、算法分析、系统结构等相关知识,它将计算机科学与数学知识很好地结合起来,比一般数学更加重视实践应用。但是在我国传统的计算机数学教学中,教师往往只重视理论知识的巩固和学习,照本宣科,将数学知识与计算机应用的实践相分离,导致计算机数学成为一门难度较大又比较单一和枯燥的学科。这不仅不利于学生掌握计算机数学的精髓,也在很大程度上影响了学生的积极性,使得传统的计算机数学教学效果事倍功半。为了满足我国现代化教育课程改革的发展需求,培养综合能力较强的新型人才,需要将计算机数学的理论知识同实践应用很好地结合起来,正是在这种形式下,计算机数学实验应运而生。
2 计算机数学实验原则
计算机数学实验课的开展是以案例式教学为基本模式。通过对实际问题进行分析,设计出实验方案,经过实验前准备、设计环节、实验操作、猜想以及归纳总结等,最终解决问题。这种实验教学方法具有很强的针对性和实践性。其基本的实验原则包括自主性原则、协调性原则、趣味性原则、探究性原则和实用性原则等。通过计算机数学实验课的开展和应用,不仅能够使学生很好地理解相关的概念,也能提高学生解决实际问题的能力。
3 计算机数学实验存在问题
就目前而言,我国的计算机数学实验课程的开展和应用还存在或多或少的问题。比如,学生和教师普遍受到传统计算机数学教学模式和理念的影响,对计算机数学实验没有引起足够额的重视,没能真正发挥计算机数学实验的实践和指导作用 ;教师在开展计算机数学实验的过程中,暴露出计算机技术不过关的问题,严重影响了计算机科学实验课程的教学效果 ;在计算机数学实验教学过程中,教学设计环节不够严谨和循序渐进,增加了学生的学习难度和压力,影响了学生的学习积极性 ;有些学校的硬件设施不合格导致无法顺利开展计算机数学实验课程等等。
4 应用改进措施
4.1 增强实验意识
在计算机数学实验的教学过程中,不论是教师还是学生,都应该打破传统的计算机数学教学理念和模式,应该从思想上重视计算机数学实验的教学和应用。计算机数学实验不仅需要学生掌握相关的定义、结论等理论知识,也需要学生具备一定的计算机实践应用能力。计算机数学教师应该将相关的实验操作应用当成自己授课内容的一部分,在备课和课程设计环节重视实验的应用。只有重视计算机数学实验,才能真正将计算机理论知识与实践应用相结合,激发学生的学习兴趣,能够在很大程度上提高学生的实践能力、动手能力、分析问题和独立解决问题的能力以及创新思维及创新能力。
4.2 建设师资力量
计算机数学实验课的开展和应用对教师队伍的整体素质提出了更高的要求。计算机数学实验课不仅要求教师具备专业的熟练的数学理论知识,还应该具备一定的计算机操作能力和应用能力。应该定期组织对计算机数学教师的培训,一方面加强和提高计算机数学教师的计算机软件和硬件的相关知识,另一方面在一定的数学技能基础上增强计算机数学教师的实验能力和科研能力,以便在计算机数学实验的应用中能够很好地指引和指导学生,为学生提供科学合理的实验技巧和策略。
4.3 完善教学设计
在计算机数学实验的教学过程中,教师应该结合计算机科学与数学知识相关内容,根据学生的接受能力和学习情况合理地设计教学环节。由于计算机数学实验是一门新兴的课程,教师尤其要注意这门课程教学过程中的方式和方法。在教学过程中,教师应该加强对计算机知识的掌握,设计出能够有效将计算机数学理论知识转为实际应用的实验方案,应该通过实验的的设计和开展,引领学生发现问题并促进学生进行独立地思考问题和解决问题,善于培养学生正确的、科学的思维方法。在计算机数学实验的开展和应用过程中,教师应该完善教学设计,使教学环节层层相扣、循序渐进,使学生在实验过程中的提出问题、猜想、评估、操作、归纳总结以及与教师和其他同学的交流过程中,熟练掌握计算机数学的理论知识和实践应用能力。
4.4 加强硬件设施
计算机数学实验的教学网络设施同其他的计算机操作技术应用设施不同。为了促进计算机数学实验的有效开展和应用,应该加强学校的硬件设施,保证计算机数学实验课程能够在计算机网络硬件设施的保障下顺利开展。
5 结语
计算机数学是一门综合了计算机科学和数学知识的学科,具有很强的实践性,通过开展计算机数学实验能够将计算机数学理论知识与实践应用相结合,有效地提高了计算机数学课程的教学效果。
摘要:计算机数学是将计算机科学与数学知识相结合的一门综合学科,它充分利用了计算机科学中编译理论、容错诊断、操作系统、逻辑设计、数据结构、机器定理证明、算法分析、系统结构等相关知识,比一般数学更加重视实践应用。通过将开设计算机数学实验课,能够激发学生的学习兴趣,将计算机数学的理论知识与实践应用很好地结合起来,也能提高学生的动手能力、综合能力以及创新能力。
关键词:计算机实验室设备 实验教学管理 网络化管理
计算机实验室在现代化教学中起着举足轻重的作用,计算机实验室的教学设备和实验教学的管理工作是实验室管理中最为重要的部分。就目前来看,其管理水平不仅影响到了实验器材的使用效率,而且还会影响到教学与科研的正常开展。经过笔者对所在院系的调查与了解,部分计算机实验室设备与实验教学管理方面是存在着一些问题的,在管理方面还有不尽人意的地方,主要原因就是管理模式和手段相对落后。这样的模式甚至已经不符合现代化教学的要求了。所以,改进其管理水平就非常必要和重要。
一、高职院校计算机实验室设备及实验教学管理现状
计算机实验室是高职院校培养学生的实践能力和创新能力的重要场所,我院为了满足教学的要求,非常重视计算机实验室设备(计算机实验室设备主要是计算机)的更新及增加,现有计算机机房(实验室)17个,设备的管理工作越来越繁重,但管理模式还是以传统的重行政轻技术的管理模式。计算机机房管理普遍存在以下问题。
(一)计算机机房管理员的水平有待提高
计算机机房是学校教学工作的一部分,本身其工作是比较重要的,但是很多机房的管理者本身不是专业的管理人员,缺乏专业素质和技能,这就往往导致在机器使用效率和日常保养与维护方面不足。对于他们来说,技能方面应该具备相应的计算机基础与网络通讯能力,如可以熟练使用计算机,并对计算机出现的问题及时解决,以保证学生正常上课、参加实践活动。
(二)硬件维护能力较差
一般的机房管理人员经验较少,难以及时发现问题,或者是即便发现了问题但是不具备修护硬件的能力。硬件维护不及时,减少了设备的使用期限,提高了使用成本,损失严重,影响教学工作的正常进行。
(三)软件维护不规范
第一,使用计算机实验室的专业比较多,既要解决本专业的计算机实验问题也要解决其他专业的,我院计算机专业有11个班,其他各系20几个专业,共同使用17个机房,工作量负荷大。第二,众多的专业课实验所需的软件维护、升级问题较多。第三,软件自由选择性高,管理不规范。可以自由选择的软件数量众多且在质量上良莠不齐,软件的重复装卸,加重了实验室管理的强度,软件频繁的装卸同时影响计算机的运行速度。第四,随着计算机网络的迅速发展,网络病毒的传播速度日益快速,病毒破坏性轻微的是影响计算机的运行速度,严重的是可以让计算机瘫痪、报废。与此同时,计算机实验室是一个局域网,病毒的传播速度非常快,破坏的波及范围特别广,有效管理难度大。
(四)机房的环境差
由于学生较多,机房又相对少,机房没有空闲时间,这样卫生方面就不能保证。所以,要做好空气流通与交换的工作,要经常性地打开窗门,特别是夏天的时节,要注重合适的降温与防潮举措,在实验室空闲的时候,做好卫生,确保干净整洁,定期做好键盘和鼠标消毒工作。
二、加强管理的意义
信息时代的到来对于教学管理过程中信息化要求的水平越来越高,作为高校来说,重视计算机实验室设备及实验教学网络化的管理,可以提高其使用效率、延长其使用周期,并且能够更好地服务于学校的教学工作,提升专业教学水平,且有利于进一步提高学生的动手能力和实践能力,为学生的全面发展奠定坚实的基础。
三、科学进行管理
既然计算机实验教学对于发展高校教学有着很重要的意义,那么应该从哪些方面着手呢?
(一)要明确教学任务
现在高校计算机教学实验室所承载的教学任务较重,必须要结合学校课程的设置来科学、细致地安排教学任务。要在实验教学网络化管理的基础上及时向师生呈现教学安排以及相关的动态信息,保证师生们结合教学计划和任务安排好自己的教学、学习计划。
(二)要提前准备好实验教学资料
包含有:各计算机课的实验教学大纲、多媒体课件、电子教案、电子教材、素材、作业、实验报告、教学动态信息等。模块中的教学大纲、多媒体课件、电子教案、电子教材、素材、作业布置、教学动态信息是由各实验课程的任课教师提供。作业、实验报告的数字化、网络化管理,有助于教师的实时批改及信息反馈,学生及时纠正错误,从而有效提高学习效率。同时,有助于教学管理部门对实验教学的内容、组织、质量进行监督、评估、督促,从而促进计算机实验教学水平的不断提高。
(三)要做好上机管理
包含有:班级信息管理、上机实时管理。班级信息管理子模块中的学生个人信息通过办理上机证,证件上提供学生的信息,通过刷卡上机,就能把学生本次上机的信息录入,如学生的考勤、所用机就能登记在册,从而完成学生考勤的实时管理、计算机实时运行情况的管理。
(四)要准确做好教学日志
包含有:教学信息登记,如此次实验课的应上课时、实上课时、缺上课时、缺上原因、补救方法、实验内容、机器运行情况、机房环境情况等。这些信息均由实验课程任课教师填写。这个模块的实时信息,有助于教学管理部门对计算机实验课任课教师的工作态度进行了解,有效对教师工作态度进行约束,促进其认真、负责。
总之,高校计算机实验室设备及实验教学工作,对于高校教学工作的正常开展非常重要,对于学校信息化教学非常关键,从细节着手优化每一个工作环节,不仅能够更好地服务于学校师生的教学,对于提高教学质量也非常重要,从而使高职院校的教学工作获得新发展。
参考文献:
[1]实验室与资产管理处.高等学校实验室管理概论[M].哈尔滨:哈尔滨工程大学出版,2007.
[2]梁斌,孔维宏,黄炎波,程智.网络教育软件设计与开发[M].北京:国防工业出版社,2006.
[3]彭伟利,王增才,张小印.高校实验室仪器设备的全程化管理[J].实验技术与管理,2009.
[4]薛节.学校计算机实验室管理系统的开发研究[J].中国科技信息,2005.
[5]林明河.高校实验室建设与仪器设备管理工作的研究[J].实验技术与管理,2007.
实验一:认识计算机系统各个硬件及外设
实验目的:了解计算机系统各个硬件的外形、特征 实验重点:掌握各个部件在机箱内的位置 实验难点:各个部件的防接错特征 实验步骤:
1. 用螺丝刀拆卸计算机各个硬件,注意轻拿轻放,保护好螺丝不要丢失
2. 根据学过的每个硬件的知识观察各个硬件的外形、特征
3. 观察每个硬件在机箱里的位置
4、写出实验心得体会
实验二:AMD,Intel CPU编号识别
实验目的:了解AMD,Intel CPU外形、接口特征
实验重点:AMD,Intel CPU编号的辨别 实验难点:AMD,Intel CPU的防接错特征 实验步骤:
1、根据每个人的电脑内的CPU来分别辨别不同厂商的CPU、型号、接口类型
2、观察AMD及Intel CPU 外形、接口特征
3、在实验报告上写出自己的CPU 厂商、型号、接口类型
实验三:AMD,Intel CPU和风扇的安装 实验目的:掌握AMD,Intel CPU的安装方法
实验重点:AMD,Intel CPU安装方法
实验难点:AMD,Intel CPU的防接错特征 实验步骤:
1、根据每个人的电脑内的CPU来分别辨别不同厂商的CPU、型号、接口类型
2、观察AMD及Intel CPU 外形、接口特征
3、安装AMD或Intel CPU到主板的CPU插槽上,同时安装散热风扇
实验四:认识主板的结构
实验目的:了解AMD,Intel CPU外形、接口特征
实验重点:AMD,Intel CPU编号的辨别 实验难点:AMD,Intel CPU的防接错特征 实验步骤:
2、根据每个人的电脑内的CPU来分别辨别不同厂商的CPU、型号、接口类型
2、观察AMD及Intel CPU 外形、接口特征
3、在实验报告上写出自己的CPU 厂商、型号、接口类型
实验四:认识主板的结构
实验目的:了解主板的结构和组成原理 实验重点:主板上各个元器件的识别
实验难点:主板上每个电子元器件的位置及特征
实验步骤:
1、观察自己的主机内的主板的厂商、型号
2、观察主板上的各个电子元器件,能指出其名字
3、观察南北桥芯片组及各种外设接口
实验六:主板驱动程序的安装
实验目的:掌握主板驱动程序的安装过程 实验重点:不同主板的驱动安装 实验难点:找到对应的主板驱动程序 实验步骤:
1、通过优化大师查看自己的主板的型号及厂商
2、下载驱动程序或把主板光盘自带的驱动程序放入光驱
3、安装驱动程序,重启
实验七:内存的识别及参数测试 实验目的:了解内存的外形、接口特征 实验重点:内存的安装 实验难点:参数的测试 实验步骤:
1、根据每个人的电脑内存来分别辨别不同厂商的内存型号、接口方式
2、观察不同类型的内存的外形、接口特征
3、在实验报告上写出自己的内存厂商、型号、接口类型及容量
4.用内存测试工具软件Hwinfo32测试内存,观察内存的参数指标
实验八:主流硬盘的编号参数识别
实验目的:了解主流硬盘的编号参数和接口类型 实验重点:主流硬盘的编号识别 实验难点:硬盘的接口连接 实验步骤:
1、根据每个人的电脑硬盘来分别辨别不同厂商的硬盘型号、容量、接口方式
2、观察不同类型的硬盘的外形、接口特征
3、在实验报告上写出自己的硬盘的厂商、型号、接口类型及容量
实验九:电源各种引线接口的连接
实验目的:了解电源中各种引线的接口及连接设备 实验重点:电源的引线连接到设备中 实验难点:电源的安装 实验步骤:
1、根据每个人的电脑电源来分别辨别不同厂商的电源型号、引线的接口
2、观察不同类型的电源的外形、接口特征
3、在实验报告上写出自己的电源的厂商及接口的阵脚数
实验十:键盘和鼠标的安装
实验目的:掌握键盘和鼠标的安装方式 实验重点:键盘鼠标的安装 实验难点:接口的识别 实验步骤:
1、根据每个人的电脑键盘和鼠标来分别辨别不同厂商的键盘和鼠标的类型和厂商
2、观察键盘和鼠标的外形、接口特征
3、在实验报告上写出自己的键盘和鼠标的生产厂商及接口方式
实验十一:显示器的相关设置 实验目的:掌握显示器的菜单设置
实验重点:对于分辨率、语言、对比度、亮度的设置 实验难点:显示器的水纹、消磁功能的设置 实验步骤:
1、根据每个人的显示器的类型来辨别不同厂商的显示器的类型
2、观察显示期的种类、接口特征、及厂商
3、在实验报告上写出自己的显示器的生产厂商及类型
4、运用显示器上的主菜单设置语言、对比度、亮度、尺寸、消磁、水纹等功能
实验十二:计算机组装实训
实验目的:掌握计算机中各种硬件的组装和连线 实验重点:计算机中各种硬件的组装 实验难点:各种硬件的数据及电源线连接 实验步骤:
1、把各种硬件按照组装的步骤把每个硬件按照到主板上固定好主板到机箱上
2、注意螺丝不要拧死,硬件安装到位
3、连接各种数据线和电源线
4、连接外设
5、通电检测
6、排除故障
实验十三:OFFICE 2003的安装与删除 实验目的:掌握office2003的安装与删除的方法 实验重点:office2003安装的步骤及目录 实验难点:安装时有选择的安装软件 实验步骤:
1、把准备好的OFFICE 2003安装程序通过开始菜单----控制面板—添加删除程序
2、如果是.EXE程序直接安装到制定的目录
3、打开各个程序看看程序安装是否正确
4、删除OFFICE 2003软件
实验十四:OFFICE 2003的安装与删除 实验目的:掌握office2003的安装与删除的方法 实验重点:office2003安装的步骤及目录 实验难点:安装时有选择的安装软件 实验步骤:
4、把准备好的OFFICE 2003安装程序通过开始菜单----控制面板—添加删除程序
5、如果是.EXE程序直接安装到制定的目录
6、打开各个程序看看程序安装是否正确
—数据结构
班号: 0316102 学号: 031650106
姓名: 郭砚璞 Email: 2755858446@qq.com
签名:
南京航空航天大学
2018年10月21日
目录
目录…………………………………………………………2
实验一:约瑟夫斯问题求解………………………………3
实验二:停车场管理问题…………………………………12
实验三:管道铺设施工的最佳方案问题…………………25
实验四:内部排序算法的实现与比较……………………35
参考资料……………………………………………………44
源程序清单…………………………………………………44
实验一、约瑟夫斯问题求解
一、问题描述
1)问题描述
约瑟夫斯(Josephus)问题的一种描述是:编号为 1,2,…,n 的 n 个人按顺时针方向
围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值 m,从
第一个人开始按顺时针方向自 1 开始报数,报到 m 时停止报数。报 m 的人出列,将他的密码作为新的 m 值,从他在顺时针方向下一个人开始重新从 1 报数,如此下去,直至所有的人全部出列为止。试设计一个程序,按出列顺序印出各人编号。
2)实验目的与基本要求
利用单向循环链表存储结构模拟此过程,按照出列的顺序印出各人的编号。
3)测试数据
n=7,7 个人的密码依次为:3,1,7,2,4,8,4。m 初值为 6(正确的出列顺序应为
6,1,4,7,2,3,5)。
4)提示
程序运行后,首先要求用户指定初始报数上限 m,然后读取个人的密码。可设 n≤30。注意链表中空表和非空表的界限。
5)输入输出
输入数据:建立输入处理,输入 n 输入以及每个人的密码;m 的初值。
输出形式:建立一个输出函数,输出正确的序列。
6)选作内容
添加采用顺序存储结构实现问题求解的模块。
以上是本实验的题目要求,下面我将介绍我的实现算法,程序调试结果以及编程过程中遇到的具体问题,并且谈谈我的收获和感悟!
二、需求分析
1、本实验用于求出一组排列数的约瑟夫斯出列顺序。
2、程序运行后显示提示信息,提示用户输入人数n和初始报数上限m,程序需判断m与n的大小,如果m>n,需提示用户重新输入n值和m值。
3、m和n输入有效后,程序提示用户继续输入n个数据,作为n个人的密码。
4、用户输入完毕后,程序需自动显示输入的数据,并且按照出列顺序将n个出列者的编号结果显示出来。
三、概要设计
为了实现上述功能,应以循环链表的数据结构存储n个人的编号、密码信息和顺序关系,因此需要一个循环链表的数据类型。
1、循环链表抽象数据类型定义:
ADT CircularLinkList{
数据对象:一个循环链表,每个结点数据域是一个人的编号和密码。
数据关系:一个结点的指针域指向按照编号下一个结点。
基本操作:
CREATE_SL(SLNODE*);//构建顺序链表
ShowOutput(SLNODE *h, int m);//递归程序,按顺序依次输出出列者的编号
}ADT CircularLinkList
2、本程序保护模块
主函数模块
建立链表模块:将输入数据赋给结点数据域,并构建循环链表的数据关系
核心算法模块:按照算法移动指针、删除节点,依次输出出列者的编号。
调用关系:
3、算法流程图
四、详细设计
1.元素类型、结点类型和结点指针类型:
#define ElemType int
#define SLNODE struct sl_node
SLNODE
{
ElemType data[2];
SLNODE *next;
};
2、建立链表的伪码
SLNODE *CREATE_SL(SLNODE *h,int n)//创建一个h为头指针的链表,h指向的结点数据域用不到
{
ElemType data;
int i = 1;
SLNODE *p, *s;
p = h;
while(i<=n)
{
printf(“请输入第%d个元素:t”,i);
scanf_s(“%d”, &data);
s =(SLNODE *)malloc(sizeof(SLNODE));
s->data[0]=i;
s->data[1] = data;
if(h->next == NULL)
{
h->next = s;
}
else
{
p->next = s;
}
p = s;
i++;
}
p->next = h;
return h;
}
3、主函数伪码
int main()
{
int m,n,mistake=1;
SLNODE *Head;
PrintInformation1();//输出程序信息和个人信息
while(mistake)
{
printf(“输入人数n:n”);
scanf_s(“%d”, &n);
printf(“请指定初始报数上限m(m应必须小于等于n):n”);
scanf_s(“%d”, &m);
if(m>n)
{
printf(“输入数据有误,请重新输入n”);
}
else mistake=0;
}
Head =(SLNODE *)malloc(sizeof(SLNODE));
Head->next = NULL;
Head = CREATE_SL(Head,n);
ShowInput(Head,n);
printf(“正确的出列顺序为:rn”);
ShowOutput(Head,m);
PrintInformation2();//程序结束信息
system(“pause”);
return 0;
}
五、调试分析与核心算法解释
程序的调试主要是针对循环链表,所以调试对象明确,按照算法思路来调试,难度不大。
本题在建立好链表以后,开始执行核心程序ShowOutput递归函数,也就是想办法按照约瑟夫斯问题的规则来删除指针指向的结点、移动指针等,从而以一定排列输出n个人的密码。程序刚开始,先由用户依次输入人数n和初始报数上限m,并判断是否m<=n,如果m>n,则显示重新输入(程序并不会结束)。
然后程序建立头指针Head并且执行CREATE_SL函数,创建链表。
执行ShowInput函数,将n个人的密码依次输出。
下面开始执行本程序的关键函数,也是整个算法的核心函数ShowOutput,这也是整个算法的体现:
函数整体是个递归函数,运用递归的思想,效率很高,占用内存小,不需要设置标志位来判断是否某个结点被访问,而是访问到一个应该出列的结点“出列”,然后以此结点为下一次递归的头结点,然后删除本次递归程序充当头结点的那个结点。
图解:
h,p,s均为指向节点的指针,第一次执行此函数时,h指向头结点。
p指针寻找到要“出列”的节点,h指向要出列的结点作为下一次递归的新的头结点。
利用p指针和s指针重新改造循环链表,然后s指针用于记录本次递归的头结点位置,即将用于删除、释放空间。
下面执行free(s),删除所指内存空间,开始下一次递归调用。
后面执行递归函数时,h刚开始指向的是上一次输出的结点(还没删除),程序一开始先让s指向h,等这一趟程序快结束找到下一个要出列的结点时,h指向该结点作为下一次递归函数的头结点,并且让p找到s指向的充当本次头结点的结点,把它删除,再执行此递归程序。
终止条件是p->next=h,说明没有需要输出的节点了,于是便实现了递归。如图所示:
截图如图:
六、使用说明
按照程序界面指示输入即可,逐个整数数字输入,每输入一个数字按一个回车。
七、调试结果
按照测试要求进行了测试,结果如下:
八、遇到的问题及解决方法(程序调试日志)
2018/9/不详
问题:先建立了一个链表实现插入算法的小功能,再进行约瑟夫问题求解,结果程序不停的输出不完整的数据,陷入死循环。
解决:p指针所指空间逻辑上不该释放但被不正确释放,删去free(p)代码,一切正常。
2018/9/不详
问题:递归程序死循环。
解决:单步执行发现递归的终止条件不正确,修改为p->next=h,程序功能实现!
2018/10/20
最后一天,完善程序,将程序中的注释写清楚,百度找到了显示系统时间的方法,按格式输出,截屏、书写报告。
九、实验的收获与感想
个人感想:循环链表虽然不是很容易理解,但是处理约瑟夫斯这样的删除元素的操作真的十分便利,比起数组要方便的多。但是代价是编程要仔细,不要释放错内存空间。
个人方法优点:
1、建立链表时,将头结点和头指针同时运用,使头指针一开始指向头结点,这样操作方便,同时个人的算法要利用s删除上一次h指向的头结点,所以一开始让头指针指向一个头结点对于个人的算法是有一定好处的。
2、本人采用递归的算法,每次找到要出列的点后,先不马上删除结点,而是将h指针指向此结点作为下一次递归的h结点,等下一次递归找到新的出列结点并用h指向来作为头结点后,再将废弃结点删除,这样“改变头结点”,操作简便,很适合递归的条件。
个人方法缺点:本人认为此程序缺点是陌生人刚看到此程序不能马上理解,因为递归程序本身不易理解。所以为了更好给别人使用,本人已将程序注释的很清楚了。
建议:本实验很好,建议像第四题那样,增加一项计算程序空间复杂度和时间复杂度(移动次数)的要求,组织同学进行讨论,展示最优的算法。
十、源程序
见源程序清单。
实验二、停车场管理问题
一、问题描述
1)问题描述
设停车场是一个可停放 n 辆汽车的狭长通道,且只有一个大门可供汽车进出。汽车在停车场内按车辆到达时间的先后顺序,依次由北向南排列(大门在最南端,最先到达的第一辆车停放在车场的最北端)。若停车场内已经停满 n 辆车,那么后来的车只能在门外的便道上等候。一旦有车开走,则排在便道上的第一辆车即可开入。当停车场内某辆车要离
开时,在它之后进入的车辆必须先退出车场为它让路,待该辆车开出大门外,其他车辆再
按原次序进入车场。每辆停放在车场的车在它离开停车场时必须按它停留的时间长短缴纳
费用。试为停车场编制按上述要求进行管理的模拟程序。
2)基本要求
以栈模拟停车场,以队列模拟车场外的便道,按照从终端读入数据的序列进行模拟管
理。每一组输入数据包括三个数据项:汽车的“到达”(‘A’表示)或“离去”(‘D’表示)信息、汽车标识(牌照号)以及到达或离去的时刻。对每一组输入数据进行操作后的输出信息为:若是车辆到达,则输出汽车在停车场内或者便道上的停车位置;若是车辆离去,则输出汽车在停车场停留的时间和应缴纳的费用(便道上停留的时间不收费)。栈以顺序
结构实现,队列以链表结构实现。
3)测试数据
设 n=2,输入数据为:(‘A’,1,5),(‘A’,2,10),(‘D’,1,15),(‘A’,3,20),(‘A’,4,25),(‘A’,5,30),(‘D’,2,35),(‘D’,4,40),(‘E’,0,0)。每一组输入数据包括三个数据项:汽车 “到达”或“离去”信息、汽车牌照号码及到达或离去的时刻,其中,‘A’表示到达;‘D’表示离去,‘E’表示输入结束。其中:(‘A’,1,5)表示 1 号牌照车在 5 这个时刻到达,而(‘D’,1,15)表示 1 号牌照车在 15 这个时刻离去。
4)提示
需另设一个栈,临时停放为给要离去的汽车让路而从停车场退出来的汽车。输入数据
按到达或离去的时刻有序。栈中每个元素表示一辆汽车,包含两个数据项:汽车的牌照号 码和进入停车场的时刻。
5)输入输出:
输入数据:
程序接受 5 个命令,分别是:到达(‘A’,车牌号,时间);离去(‘D’,车牌号,时 间);停车场(‘P’, 0, 0)显示停车场的车数;候车场(‘W’, 0, 0)显示候车场的车数;退出(‘E’, 0, 0)退出程序。
输出数据:
对于车辆到达,要输出汽车在停车场内或者便道上的停车位置;对于车辆 离去,则输出汽车在停车场停留的时间和应缴纳的费用(便道上不收费)。
二、需求分析
1、本程序用来模拟停车场进场、进便道、场外等候、出场、收费等操作。
2、程序运行后显示提示信息,提示用户输入停车每小时需缴纳的费用,用户输入后,提示信息提示用户输入命令:驶入停车场A,离开停车场D,查看停车场内车数P 0 0,查看候车厂内车数W 0 0,程序结束E 0 0。
3、程序需判断用户输入的进场出场时间的有效性,后来输入的时间要大于以前输入的时间。
4、用户输入有效命令后,程序显示汽车进出场信息,若是车辆到达,则输出汽车在停车场内或者便道上的停车位置;若是车辆离去,则输出汽车在停车场停留的时间和应缴纳的费用。
三、概要设计
为了实现上述功能,需要用栈模拟停车场,用一个备用的栈存储暂时出场的外部汽车,用队列模拟便道。
1、停车场“栈”抽象数据类型定义:
ADT stack{
数据对象:车牌号、进场时间、汽车数量
数据关系:先入后出
基本操作:
*Init_Parking();//置空栈
IsEmpty_Parking(Parking *s);//判空栈
Push_Parking(Parking *s,ElemType license,ElemType timeIn);//入栈
Pop_Parking(Parking *s,ElemType *license,ElemType *timeIn);//出栈
}ADT stack
2、备用存储“栈”抽象数据类型定义:
ADT stack1
{
数据对象:车牌号、进场时间、汽车数量
数据关系:先入后出
基本操作:
*Init_Backup();//置空栈
IsEmpty_Backup(Backup *s);//判空栈
Push_Backup(Backup *s, ElemType license, ElemType timeIn);//入栈
Pop_Backup(Backup *s, ElemType *license,ElemType* timeIn);//出栈
}
3、链式队列抽象数据类型定义:
ADT linkqueue
{
数据对象:车牌号、汽车数量
数据关系:先入先出
基本操作:
*Init_LQueue();//创建一个带头结点的空队
In_LQueue(LinkQueue *q, ElemType license);//入队
IsEmpty_LQueue(LinkQueue *q);//判队空
Out_LQueue(LinkQueue *q, ElemType *license);//出队
}
4、本程序保护模块
主函数模块
进场模块:对于进场的命令进行完善地操作处理并进行状态显示的模块
出场模块:对于出场的命令进行完善地操作处理并进行状态显示的模块
置空栈、置空队、进出栈、进出队、判栈空栈满、判队空队满模块:对栈、备用栈、队列进行的基本操作
调用关系:
5、算法流程图
四、详细设计
1、元素类型、结点类型和结点指针类型:
#define Maxsize 2 //停车场最多能停的车数
#define ElemType int
int Prize;//每停一个时刻收费多少元
static int num = 0;//num用于记录入队的车所在的位置
typedef struct stack //模拟停车场的栈
{
ElemType license[Maxsize];//用于存放车牌号
ElemType timeIn[Maxsize];//用于存放入停车场时间
int top;
}Parking;
typedef struct stack1 //退车时暂时存放
{
ElemType license[Maxsize-1];
ElemType timeIn[Maxsize-1];
int top;
}Backup;
typedef struct road
{
ElemType license;
struct road *next;
}Road;
typedef struct linkqueue//队列模拟便道
{
Road *front,*rear;
}LinkQueue;
2、部分基本操作的伪码类型
//给停车场用的配置函数
Parking *Init_Parking()//置空栈
{
Parking *s;
s=(Parking*)malloc(sizeof(Parking));
s->top=-1;
return s;
}
int IsEmpty_Parking(Parking *s)//判空栈
{
if(s->top==-1)
return 1;
else return 0;
}
int Push_Parking(Parking *s,ElemType license,ElemType timeIn)//入栈
{
if(s->top==Maxsize-1)
return 0;
else
{
s->top++;
s->license[s->top]=license;
s->timeIn[s->top]=timeIn;
return 1;
}
}
int Pop_Parking(Parking *s,ElemType *license,ElemType *timeIn)//出栈
{
if(IsEmpty_Parking(s))
return 0;
else
{
*license = s->license[s->top];
*timeIn = s->timeIn[s->top];
s->top--;
return 1;
}
}
//给备用栈配置的函数
Backup *Init_Backup()//置空栈
{
Backup *s;
s =(Backup*)malloc(sizeof(Backup));
s->top =-1;
return s;
}
int IsEmpty_Backup(Backup *s)//判空栈
{
if(s->top ==-1)
return 1;
else return 0;
}
int Push_Backup(Backup *s, ElemType license, ElemType timeIn)//入栈
{
if(s->top == Maxsize-1)
return 0;
else
{
s->top++;
s->license[s->top] = license;
s->timeIn[s->top] = timeIn;
return 1;
}
}
int Pop_Backup(Backup *s, ElemType *license,ElemType* timeIn)//出栈
{
if(IsEmpty_Backup(s))
return 0;
else
{
*license = s->license[s->top];
*timeIn = s->timeIn[s->top];
s->top--;
return 1;
}
}
//给候车便道链式队列配置的函数
LinkQueue *Init_LQueue()//创建一个带头结点的空队
{
LinkQueue *q;
Road *p;
q =(LinkQueue*)malloc(sizeof(LinkQueue));
p =(Road*)malloc(sizeof(Road));
p->next = NULL;
q->front = q->rear = p;
return q;
}
void In_LQueue(LinkQueue *q, ElemType license)//入队
{
Road *p;
p =(Road*)malloc(sizeof(Road));
p->license = license;
p->next = NULL;
q->rear->next = p;
q->rear = p;
}
int IsEmpty_LQueue(LinkQueue *q)//判队空
{
if(q->front == q->rear)
return 1;
else
return 0;
}
int Out_LQueue(LinkQueue *q, ElemType *license)//出队
{
Road *p;
if(IsEmpty_LQueue(q))
{
printf(”队空“);
return 0;
}
else
{
p = q->front->next;
q->front->next = p->next;
*license = p->license;
free(p);
if(q->front->next == NULL)
q->rear = q->front;
return 1;
}
}
3、主函数的伪码
void main()
{
ElemType license, time,timelast=0;//timeInlast是最近一次有车进停车场的时间,提示以后输入的进场时间要大于此数值
char command;//进入A还是离开D
Parking *s;
Backup *s1;
LinkQueue *q;
PrintInformation1();//输出程序信息和个人信息
s = Init_Parking();//停车场
q = Init_LQueue();//便道队列
s1 = Init_Backup();//退车时的备用栈
printf(”请输入停车每小时需交纳的费用(元)rn“);
setbuf(stdin, NULL);//使stdin输入流由默认缓冲区转为无缓冲区,必不可少
scanf(”%d“,&Prize);
setbuf(stdin, NULL);//使stdin输入流由默认缓冲区转为无缓冲区,必不可少
while(1)
{
setbuf(stdin, NULL);//使stdin输入流由默认缓冲区转为无缓冲区,必不可少
Loop:printf(”请输入操作的命令,驶入停车场A,离开停车场D,查看停车场内车数P 0 0,查看候车厂内车数W 0 0,程序结束E 0 0:n“);
scanf(”%c%d%d“,&command, &license,&time);
setbuf(stdin, NULL);//使stdin输入流由默认缓冲区转为无缓冲区,必不可少
if(command == A)
{
if(time <= timelast)
{
printf(”输入的时间必须大于上一次输入的时间:t“);
printf(”%dt“, timelast);
printf(”请重新输入n“);
goto Loop;
}
else
{
timelast = time;
GetIn(s,q,license,time);
}
}
if(command == D)
{
if(time <= timelast)
{
printf(”输入的时间必须大于上一次输入的时间:t“);
printf(”%dt“, timelast);
printf(”请重新输入n“);
goto Loop;
}
else
{
timelast = time;
GetOut(s, s1, q, license, time);//车开走的函数
}
}
if(command == P)
{
if(license == 0 && time == 0)
printf(”停车场内停了%d辆车n“,s->top+1);//显示停车场车数
}
if(command == W)
{
if(license == 0 && time == 0)
printf(”侯车场内停了%d辆车n“,num);//显示候车场车数
}
if(command == E)
{
if(license == 0 && time == 0)
{
PrintInformation2();//程序结束信息
system(”pause“);
return;
}
}
}
}
五、调试分析与核心算法解释
程序本身是利用栈、队列的进出完成停车场汽车进出场的模拟的,只要按照模块化的函数,按照基本的逻辑编写,调试是比较容易的。
程序一开始会要求用户输入每小时缴纳多少元费用,显示“请输入停车每小时需交纳的费用(元)”。
以栈模拟停车场,以队列模拟车场外的便道,在while循环开始让用户输入命令、车牌号、时间三个变量,对三个变量进行判断,并执行相应函数。
程序显示“请输入操作的命令,驶入停车场A,离开停车场D,查看停车场内车数P 0 0,查看候车厂内车数W 0 0,程序结束E 0 0:”
如果后来输入的时间比之前输入的时间小,程序会提示“输入的时间必须大于上一次输入的时间: xx 请重新输入”。
其中驶入函数先判断是否栈满,如果栈满则执行入队操作,否则入栈,并将车牌号、驶入时间存入栈元素数组,top值加一,用于记录车的数量,用于判断是否栈满。
如果栈不满,程序显示“车牌号为xx的汽车在xx时刻停在xx车位”。
如果栈满,程序显示“xx号车停在候车便道的第xx个位置”。
离开函数先判断是否栈空,如果栈空则输出没有车辆提示,否则进一步比较是否有栈内车牌号元素与命令的离开的车牌号一致,有则出栈,计算停车时间和计价,无则输出没有此车牌号的车的提示。
如果没有命令的车牌号的汽车,则显示“对不起!停车场内没有车牌号为xx的车”。
如果停车场已空,会显示“对不起!停车场已空!”。
如果原先栈满,离开一辆车以后,最早到便道上的一辆车进栈,并显示“xx号汽车此时退出便道,进入停车场最后一个位置”。
队列和栈的top记录了车的数量,可用于输出内部车数,也可用于判断是否栈满。
如果三个变量分别为P,0,0,则输出停车场内车的个数。
如果三个变量分别为E,0,0,则输出便道上车的个数。
如果三个变量分别为E ,0, 0,则结束程序。
六、使用说明
程序接受 5 个命令,分别是:到达(‘A’,车牌号,时间);离去(‘D’,车牌号,时 间);停车场(‘P’, 0, 0)显示停车场的车数;候车场(‘W’, 0, 0)显示候车场的车数;退出(‘E’, 0, 0)退出程序。
注意:命令字符(A D P W E)用大写,输入的三个数据之间用空格隔开。如A 1 5。代表1号1号汽车在5时刻进场。
七、调试结果
按照测试要求给的数据进行了测试:
八、遇到的问题和解决方法(程序调试日志)
2018/9/不详
问题:程序全部结束,执行时能基本完成功能,但是总是会间隔有一次命令无效,重复输出“请输入命令.......”。
解决方法:后来百度发现,这是因为数据缓存区没有清除的缘故,每次回车都会在数据缓存区遗留下来一个Enter字符,可被char型变量读取,因此在每次输入数据前后加入一个清除数据缓存区的函数setbuf(stdin, NULL)即可解决问题。
2018/10/20
最后一天,完善程序,将程序中的注释写清楚,百度找到了显示系统时间的方法,按格式输出,截屏、书写报告。
九、实验的收获与感想
个人感想:
这道题目和后面的第四道题目都是属于比较透彻的题目,先做了第二题,还是对第二题印象最深,首先这道题很讲究编程的条理性,里面的初始化栈、判栈空、栈满、入栈、出栈以及初始化队列、判队空、队满、入队、出队等函数在书上都有,主要的工作是利用模块化的思想,由整体到局部逐渐求精地去写整个程序,从而把整个停车场的5个命令功能给实现,感觉收获很多,模块化的思想很厉害!
方法的优点:
整体程序思路比较简单,因此个人没有什么更优算法,只是在这里面有一个逻辑,就是后面输入的时间不能比之前输入的时间小,因为这不符合日常逻辑,同时也影响了入栈出栈次序,因此我程序里使用了不常用的goto函数,一般这个函数是不建议用的,它会跳转程序,但是在这里判断后面输入的时间大于之前输入的时间后,goto函数可以让程序跳转到while循环开始的地方,让用户重新输入命令,这里感觉很方便!
建议:
希望多多布置这样的习题,有助于教会学生利用模块化思想,不过希望布置的题目可以是多方向的比如有关界面制作的题目,把模块化的函数给大家,大家进行使用,根据自己爱好设计出相应的模块化功能的程序。
十、源程序
见源程序清单。
实验三、管道铺设施工的最佳方案问题
一、问题描述
1)问题描述
需要在某个城市 n 个居民小区之间铺设煤气管道,则在这 n 个居民小区之间只需要铺设 n-1 条管道即可。假设任意两个小区之间都可以铺设管道,但由于地理环境不同,所需要的费用也不尽相同。选择最优的方案能使总投资尽可能小,这个问题即为求无向网的最小生成树。
2)基本要求
在可能假设的 m 条管道中,选取 n-1 条管道,使得既能连通 n 个小区,又能使总投资最小。每条管道的费用以网中该边的权值形式给出,网的存储采用邻接表的结构。
3)测试数据
使用下图给出的无线网数据作为程序的输入,求出最佳铺设方案。右侧是给出的参考解。
以上是本实验的题目要求,下面我将介绍我的实现算法,程序调试结果以及编程过程中遇到的具体问题,并且谈谈我的收获和感悟!
二、需求分析
1、此程序用来求无向带权网的最小生成树。
2、程序的输入数据放在一个dat格式的文件中,想要修改输入数据,用记事本打开文件直接修改即可。任何时刻想看到结果,点击一下exe文件即可一键解决。
3、输入数据的形式是一个矩阵形式,行和列的元素依次代表A、B、C....,两点之间有边,则数据是一个不为0的数,否则为0。
4、程序运行结果不仅会在控制台显示出来,同时还要在一个新的文件中显示出来,点击一下exe文件即可一键解决,满足用户“即点即看”,输出文件令用户能“随时且长久”看到结果,不必每一次都要运行程序。
三、概要设计
为实现上述功能,应以图的邻接表数据结构,即链表与数组相结合的数据结构。
1、邻接表抽象数据类型定义:
ADT ALGraph{
数据对象:结点A、B、C....数据关系:存储结构上链表式指针相连,物理结构上点之间相连成边
基本操作:CreateALGraph(ALGraph *G);//建立无向图的邻接表存储
}ADT ALGraph
2、文件操作模块
基本操作:
read_data(void);//只读方式打开文件
read_array(double *array,int n1,int n2,FILE *fp);//读取文件中的边值信息
cout_data(void);//只写方式打开或建立文件
cout_array(double *array,int n1,int n2,FILE *fp);//向文件中写入边值信息
3、本程序保护模块
主程序模块
建立无向图模块:根据读入文件的边值信息创建无向图邻接表存储
最小生成树模块:由无向图生成最小生成树
读入数据模块:只读方式读取文件数据
输出结果模块:将结果输出到控制台
输出到文件模块:将结果输出到文件
调用关系:
四、详细设计
需要建立一个无向图的邻接表存储结构,进行最小生成树的提取。
1、元素类型、结点类型和结点指针类型:
#define MaxVertexNum 100 //设置小区数最多为100
#define VertexNum 9
double LeastNum;//用于记录最短边长度
double LongestNum;//用于记录最长边长度,程序过程中不改变
double adjacent[VertexNum][VertexNum];
//邻接矩阵,不用于处理数据,而是用于暂时存储从文件读来的数据
//进而在邻接表存储数据时读取此数组数据即可
//二维数组数据为0的元素说明之间没有通道
//在处理完数据后,此数组会用来暂时存储处理后的数据,并写入到另一个文件中
typedef struct vnode
{//顶点表结点
char vertex;
EdgeNode *firstedge;
}VertexNode;
typedef struct
{
VertexNode adjlist[MaxVertexNum];
int n,e;
}ALGraph;
2、有序表类型:
typedef struct node
{//边表结点
char adjvex;
double weight;//权值
struct node *next;
}EdgeNode;
3、主函数的伪码:
void main()
{
ALGraph *G;
PrintInformation1();
G =(ALGraph*)malloc(sizeof(ALGraph));
G->n = VertexNum;//为G指向的图分配空间,设置点数(小区数)
read_data();
CreateALGraph(G);
MinimumSpanningTree(G);
cout_data();//输出到文件
ResultOutput((double *)adjacent,VertexNum,VertexNum);//输出到控制台
PrintInformation2();
system(”pause“);
}
4、算法流程图
五、调试分析与核心算法解释
此题按照Prim算法,设置一个用于存储点的点集,找短边从一个点向两点、三个....更多逐渐扩张,即可得到最小生成树。
1).输入:一个加权连通图,其中顶点集合为V,边集合为E;
2).初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;
3).重复下列操作,直到Vnew = V:
a.在集合E中选取权值最小的边,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
b.将v加入集合Vnew中,将边加入集合Enew中;
4).输出:使用集合Vnew和Enew来描述所得到的最小生成树。
具体可以参考资料:https://baike.baidu.com/redirect/cb1fkztQc2TOscNlcMemKsGZ1fsgTprJsdBq_APeZx74W4q4TzbKXHsvSYW_6aM1DqhF56eTgD8EZLzBCQHKBGa6ExWmgXbju_gm13Qbbu0KxbHuiIS_DxEp2fgT3BU
六、使用说明
输入数据已经在”gyp_program3_Input.dat“中写好,如果想做修改可以在该文件中修改即可,输出的数据既在控制台显示,也会输出到”gyp_program3_Output.dat“。
七、调试结果
输入数据文件:
这是一个矩阵,例如:第2行,第3列代表B,C两点间的边,0代表无边,不为0代表有边。
控制台程序显示:
输出数据到输出文件
八、遇到的问题和解决方法(程序调试日志)
2018/9/不详
问题:一进入建立无向图的函数程序就中止出错。
解决方法:给建立无向图函数传递的形参是指针,而在主函数中G指针没有赋给内存空间,所以函数无法对G所指的空间进行初始化,在主程序中加入这样一句代码就好了:
G =(ALGraph*)malloc(sizeof(ALGraph));
2018/10/17
问题:输出的二维数组只有一位正常,其余全是0。如下图所示:
解决方法:后来发现是里面flag2这个标志位刚开始是1,程序执行过程中被置0用于判断,但是判断以后没有再次重置为1,导致要用很多次的标志位只发挥了一次作用,后面就误判了,在循环结束加入重置1的语句即可。
问题:输出的二维数组输出数据不完整,里面总有最小的边(问题切入点)。
解决方法:单步执行后发现,某一次循环中Leastnum这个变量得到的最小值恰好是所有边中最小的一个,它在发挥完比较作用后,没有被置为一个很大的数(不小于这些边中最大值即可),结果在下一次循环的时候,导致后面的边都比它大,以至于后面的边都被舍去了,解决方法就是每次循环第一句先把原图的最大边赋给leastnum。
问题:直接运行debug文件夹里的exe程序,且debug程序终止,怀疑是文件数据读取失败,无法打开文件,即文件不存在。
解决方法:如果不详细说明文件路径,程序本身会在当前文件夹内找文件,存数据的文件gyp_program3_Input.dat要保存在当前文件中。也就是和源代码在同一个文件夹中,但是这样子的话,只有用编程软件打开代码运行,dat文件才有效,若想在debug里直接运行exe程序,则把存数据的输入文件同名复制到debug文件夹里即可。
九、实验的收获和感想
个人感想:这个程序可以说是算法感十足了,也是我遇到问题最大的一个程序,但是也证明了自己的能力,学到了很多,收获最大的就是:对于用的不止一次的标志位,一定不可能只单方向置位,一定是双向置位,一次循环结束一定要记得置位,否则用了这一次以后,后面的循环就会误判!
Prim算法真的很好用,不仅适合求带球图的最小生成树,还适合寻找一个点到另一点的最短路径。
个人方法优点:输入方便,输出简洁。读取文件中的数据,不用手动输入,想修改数据在文件中修改就可以,另外输出有两种形式,一种是控制台输出,一种是输出到文件,输出的是一个二维数组,行和列都有表头,看起来很清晰,两个点之间若有边,相应二维坐标的元素就是边值,无边则相应的位置为0。
建议:可以要求用顺序表的方法,因为从理解和编程难度角度考虑,图的邻接表找边会很慢每次都要顺着其中一个链表头结点去寻找,不过这也很锻炼人的能力!
十、源程序
见源程序清单。
实验四、内部排序算法的实现与比较
一、问题描述
1)问题描述
在教科书中,各种内部排序算法的时间复杂度分析结果只给出了算法执行时间的阶,或大概执行时间。试通过随机数据比较各算法的关键字比较次数和关键字移动次数,以取得直观感受。
2)基本要求
(1)对常用的内部排序算法进行比较:直接插入排序、简单选择排序、冒泡排序、快速排序、希尔排序。
(2)利用随机函数产生N(如30000)个随机整数,作为输入数据作比较;比较的指标为关键字参加的比较次数和关键字的移动次数(关键字交换计为3次移动)。
(3)对结果作出简要分析。
3)测试数据
随机函数产生。
4)提示
主要工作是设法在已知算法中适当位置插入对关键字的比较次数和移动次数的计数操 作。注意采用分块调试的方法。
5)输入输出:
输入数据:参加排序的整数个数 n(如 n=30000);
输出数据:各种排序方法的关键字比较次数和移动次数(从小到大排列)。
二、需求分析
1、本程序用来比较5种排序的关键字比较次数和关键字移动次数。
2、本程序用srand()和rand()函数产生N个随机数用于排序方法的比较,用户无需输入。
3、运行程序后,程序需按从小到大的顺序分别输出5种排序的关键字比较次数和移动次数。
三、概要设计
为实现上述功能,程序需要产生N个随机数,并且需要写出这5种排序的排序函数。
1、产生N个随机数的方法
srand((unsigned)(time(NULL)));
for(int j = 0;j < N;j++)
{
num0[j] = rand();
}
2、保证每次排序的数据都相同的方法
num0数组用于得到随机数,num数组每次排序前先用num0数组赋值即可。
for(int j=0;j { num[j] = num0[j]; } InsertSort(num,N);3、5种排序函数 void InsertSort(int R[], int n);//插入排序 void SelectSort(int R[], int n);//选择排序 void BubbleSort(int R[], int n);//冒泡排序 void QuickSort(int R[],int low,int high);//快速排序 void ShellInsert(int R[],int m,int n);//快速排序 void Shellsort(int R[],int n);//希尔排序 4、本程序保护模块 主程序模块 排序模块 比较输出模块 调用关系: 4、算法流程图 四、详细设计 1、排序函数基本操作的伪码实现 void InsertSort(int R[], int n)//插入排序 { int i, j; for(i = 2;i <= n;i++) { R[0] = R[i]; MoveNum[0]++; j = i-1; while(R[0] < R[j]) { KeyCompareNum[0]++; R[j + 1] = R[j]; MoveNum[0]++; j--; } R[j + 1] = R[0]; MoveNum[0]++; } } void SelectSort(int R[], int n)//选择排序 { int i, j, k; for(i = 1;i < n;i++) { k = i; for(j = i + 1;j <= n;j++) if(R[j] < R[k]) { k = j; KeyCompareNum[1]++; } if(k!= i) { R[0] = R[k]; R[k] = R[i]; R[i] = R[0]; MoveNum[1]+=3; } } } void BubbleSort(int R[], int n)//冒泡排序 { int i, j, flag = 0; for(i = 1;(i < n && flag == 0);i++) { flag = 1; for(j=1;j if(R[j + 1] < R[j]) { KeyCompareNum[2]++; flag = 0; R[0] = R[j]; R[j] = R[j+1]; R[j + 1] = R[0]; MoveNum[2]+=3; } } } void QuickSort(int R[],int low,int high)//快速排序 { int i,j; i=low; j=high; R[0]=R[i]; MoveNum[3]++; while(i { while((R[j]>=R[0])&&(j>i)) { j--; KeyCompareNum[3]++; } if(j>i) { R[i]=R[j]; MoveNum[3]++; i++; } while((R[i]<=r[0])&&(j>i)) { i++; KeyCompareNum[3]++; } if(j>i) { R[j]=R[i]; MoveNum[3]++; j--; } } R[i]=R[0]; MoveNum[3]++; if(low QuickSort(R,low,i-1); if(i QuickSort(R,j+1,high); } void ShellInsert(int R[],int m,int n) {//一趟希尔排序,按间隔m划分子序列 int temp,j; for(int i=m;i { temp=R[i]; MoveNum[4]++; j=i; while(j>=m && temp { KeyCompareNum[4]++; R[j]=R[j-m]; MoveNum[4]++; j-=m; } R[j]=temp; MoveNum[4]++; } } void Shellsort(int R[],int n)//希尔排序 { int m; m=n/2; while(m>=1) { ShellInsert(R,m,n); m=(m==2?1:(m/2)); } } 2、主函数伪码实现 int main() { //数组设为N+1个是因为有些算法是从数组1到N存储的,0位有的不用,有的用作了哨兵 int num0[N+1];//记录最原先随机产生的N个数字,因为num[N]每排序一次都会改变 int num[N+1];//每次排序前先读入num0[N]数据 //srand函数只增加一次就够了,用系统当前时间设置rand()随机序列种子,保证每次运行随机序列不一样 srand((unsigned)(time(NULL))); for(int j = 0;j < N;j++) { num0[j] = rand(); } PrintInformation1(); for(int j=0;j { num[j] = num0[j]; } InsertSort(num,N); for(int j = 0;j < N;j++) { num[j] = num0[j]; } SelectSort(num,N); for(int j = 0;j < N;j++) { num[j] = num0[j]; } BubbleSort(num,N); for(int j = 0;j < N;j++) { num[j] = num0[j]; } Shellsort(num,N); for(int j = 0;j < N;j++) { num[j] = num0[j]; } QuickSort(num,0,N-1); printf(”关键字比较次数按从小到大排列分别是:rn“); KeyCompareNum_pailie(); printf(”rn“); printf(”移动次数按从小到大排列分别是:rn“); MoveNum_pailie(); PrintInformation2(); system(”pause“); return 0; } 五、调试分析与核心算法解释 程序的5种排序函数可以自己写,也可以百度找源码,总之五种排序函数写完以后,调试的关键是设置计数变量,并在这些函数的合适位置进行加1计数或加3计数,因此注意分块调试,分函数调试,做到这几点调试难度总体不大。 六、使用说明 随机数产生,5种排序用的都是同一组N个随机数,用户无需输入,直接运行程序即可输出运算结果。 七、调试结果 八、遇到的问题和解决方法(程序调试日志) 2018/10/19 问题:第一种排序输出很大,后面输出很小,几乎没作用。 解决方法:每经过一个排序函数,数组已经排好序了,不能直接调用其余的排序函数,而是要在程序一开始就用另一个数组num0[N]记录了随机数产生的数组num[N],因此只需要在每次排序前,把num0数组中数据重新赋给num数据即可参与排序了。 问题:数据输出个数少于5个,单步执行发现循环不到5次。 解决方案:分析后发现,程序的几个for循环,内层的循环里面的计数加1变量如i,j,和外层循环设置的加1变量用的是一个变量,导致内层循环计数变量的改变会影响外层循环,导致输出个数小于5。将这些变量设置成不同变量就不影响了(相互独立的循环可能不会影响,但内外层关系的两个循环绝对不能用同一个计数变量)。 问题:程序末尾会跳出一个程序中止警告框,说是栈释放的问题。 解决方案:百度发现,这实际上是数组越界的问题,把数组个数设置为N+1大小的,就好了。 九、实验的收获和感想 个人感想:这个程序难度不大,关键在于在合适的位置插入用于记录的变量+1或者+3,真正有技术含量的在于按照从小到大的顺序输出相应数据。收获比较大的一个技巧:相互独立的循环计数变量可能不会影响,但内外层关系的两个循环绝对不能用同一个计数变量,否则程序循环次数就会乱! 从关键字比较次数和移动次数来看,选择和快速排序都是非常高效的,希尔排序也不错,不要用或少用冒泡排序和直接插入排序。 个人方法的优点:只产生了1次随机数,5次排序的用的都是同一组数据,可以更好地更严谨地比较出这5种算法的优劣。 个人方法的缺点:因为要“长久”保留产生的随机数,因此需多设置一个数组,占用内存空间比较大。 十、源程序 源程序见源程序清单。 参考资料 https://blog.csdn.net/guanyasu/article/details/53153705 https://jingyan.baidu.com/article/49711c616b8a1ffa441b7cdc.html https://zhidao.baidu.com/question/***684.html 源程序清单 实验一、约瑟夫斯问题求解 #include #include #include #define ElemType int #define SLNODE struct sl_node SLNODE { ElemType data[2]; SLNODE *next; }; SLNODE *CREATE_SL(SLNODE*,int); void ShowInput(SLNODE*h,int n);//每个人的密码输入 void ShowOutput(SLNODE*,int);//排列输出 void PrintInformation1();//输出程序信息和个人信息 void PrintInformation2();//程序结束信息 void PrintTime();//输出时间 int main() { int m,n,mistake=1; SLNODE *Head; PrintInformation1();//输出程序信息和个人信息 while(mistake) { printf(”输入人数n:n“); scanf_s(”%d“, &n); printf(”请指定初始报数上限m(m应必须小于等于n):n“); scanf_s(”%d“, &m); if(m>n) { printf(”输入数据有误,请重新输入n“); } else mistake=0; } Head =(SLNODE *)malloc(sizeof(SLNODE)); Head->next = NULL; Head = CREATE_SL(Head,n); ShowInput(Head,n); printf(”正确的出列顺序为:rn“); ShowOutput(Head,m); PrintInformation2();//程序结束信息 system(”pause“); return 0; } void PrintTime() { time_t t; time(&t); printf(”%s“, ctime(&t)); printf(”rn“); } void PrintInformation1() { printf(”实验名称:实验一.约瑟夫斯问题求解rn“); printf(”学号:031650106rn“); printf(”姓名:郭砚璞rn“); printf(”====================rn“); printf(”程序运行开始,Current local time and date:“); PrintTime(); } void PrintInformation2() { printf(”rn====================rn“); printf(”程序运行结束,Current local time and date:“); PrintTime(); } SLNODE *CREATE_SL(SLNODE *h,int n) //创建一个h为头指针的链表,h指向的结点数据域用不到 { ElemType data; int i = 1; SLNODE *p, *s; p = h; while(i<=n) { printf(”请输入第%d个元素:t“,i); scanf_s(”%d“, &data); s =(SLNODE *)malloc(sizeof(SLNODE)); s->data[0]=i; s->data[1] = data; if(h->next == NULL) { h->next = s; } else { p->next = s; } p = s; i++; } p->next = h; return h; } void ShowInput(SLNODE *h,int n) { SLNODE *p; p = h; printf(”%d“,n); printf(”个人的密码依次为:“); while((p->next)!= h) { p = p->next; printf(”%dt“, p->data[1]); } printf(”n“); } void ShowOutput(SLNODE *h, int m) { SLNODE *p, *s;//s用于记录上一个节点,从而使p结点找到它将其删除 int j = 0; s = h;//第一次执行此函数时,h指向头结点;后面递归执行时,h刚开始指向的是上一//次输出的结点(还没删除) //都用s来记录,等那一趟程序快结束找到下一个要出列的的点时,h指向那个结点作为头结点,并且让p找到s指向的 //上一个结点,把它删除。 p = h; while(j < m-1) { p = p->next; if(p->next==h)//不能让h所指向的结点(上一次输出的结点,暂时用作头结点所以//还未删除)影响小循环次数 { p=p->next;//所以此处让p多移动一下,等下一次小循环让p顺利移动到下一//个节点(从而忽略掉h指向的结点) } //等找到下一个该出列的结点时,h指向那个结点(充当下一次的头节点),充当上一次头//结点的结点利用s删除 j++; }//此时p指向第m-1个结点 if(p->next == h)//整个程序的终止条件,依次回到上个函数结尾,相当于全部结束了 { return; } h= p->next; p = h;//此时h和p均指向要出列的结点 printf(”%dt“, h->data[0]); j = 0;//j用于while循环,使h指针指向要出列的点的前一个结点,所以及时清零 while(p->next!=s)//找s废弃节点 { p = p->next; } s = p->next; p->next = s->next;//连接新结点 free(s);//释放s所指空间 ShowOutput(h,h->data[1]); } 实验二、停车场管理问题 #include ”stdio.h“ #include ”stdlib.h“ #include ”time.h“ #define Maxsize 2 //停车场最多能停的车数 #define ElemType int int Prize;//每停一个时刻收费多少元 static int num = 0;//num用于记录入队的车所在的位置 typedef struct stack //模拟停车场的栈 { ElemType license[Maxsize];//用于存放车牌号 ElemType timeIn[Maxsize];//用于存放入停车场时间 int top; }Parking; typedef struct stack1 //退车时暂时存放 { ElemType license[Maxsize-1]; ElemType timeIn[Maxsize-1]; int top; }Backup; typedef struct road { ElemType license; struct road *next; }Road; typedef struct linkqueue//队列模拟便道 { Road *front,*rear; }LinkQueue; void GetIn(Parking *s, LinkQueue *q, ElemType license, ElemType timeIn);//有车进来 void GetOut(Parking *s, Backup *s1, LinkQueue *q, ElemType license, ElemType timeOut);//有车//出去 void PrintInformation1();//输出程序信息和个人信息 void PrintInformation2();//程序结束信息 void PrintTime() { time_t t; time(&t); printf(”%s“, ctime(&t)); printf(”rn“); } void PrintInformation1() { printf(”实验名称:实验二.停车场管理问题rn“); printf(”学号:031650106rn“); printf(”姓名:郭砚璞rn“); printf(”====================rn“); printf(”程序运行开始,Current local time and date:“); PrintTime(); } void PrintInformation2() { printf(”rn====================rn“); printf(”程序运行结束,Current local time and date:“); PrintTime(); } //给停车场用的配置函数 Parking *Init_Parking()//置空栈 { Parking *s; s=(Parking*)malloc(sizeof(Parking)); s->top=-1; return s; } int IsEmpty_Parking(Parking *s)//判空栈 { if(s->top==-1) return 1; else return 0; } int Push_Parking(Parking *s,ElemType license,ElemType timeIn)//入栈 { if(s->top==Maxsize-1) return 0; else { s->top++; s->license[s->top]=license; s->timeIn[s->top]=timeIn; return 1; } } int Pop_Parking(Parking *s,ElemType *license,ElemType *timeIn)//出栈 { if(IsEmpty_Parking(s)) return 0; else { *license = s->license[s->top]; *timeIn = s->timeIn[s->top]; s->top--; return 1; } } //给备用栈配置的函数 Backup *Init_Backup()//置空栈 { Backup *s; s =(Backup*)malloc(sizeof(Backup)); s->top =-1; return s; } int IsEmpty_Backup(Backup *s)//判空栈 { if(s->top ==-1) return 1; else return 0; } int Push_Backup(Backup *s, ElemType license, ElemType timeIn)//入栈 { if(s->top == Maxsize-1) return 0; else { s->top++; s->license[s->top] = license; s->timeIn[s->top] = timeIn; return 1; } } int Pop_Backup(Backup *s, ElemType *license,ElemType* timeIn)//出栈 { if(IsEmpty_Backup(s)) return 0; else { *license = s->license[s->top]; *timeIn = s->timeIn[s->top]; s->top--; return 1; } } //给候车便道链式队列配置的函数 LinkQueue *Init_LQueue()//创建一个带头结点的空队 { LinkQueue *q; Road *p; q =(LinkQueue*)malloc(sizeof(LinkQueue)); p =(Road*)malloc(sizeof(Road)); p->next = NULL; q->front = q->rear = p; return q; } void In_LQueue(LinkQueue *q, ElemType license)//入队 { Road *p; p =(Road*)malloc(sizeof(Road)); p->license = license; p->next = NULL; q->rear->next = p; q->rear = p; } int IsEmpty_LQueue(LinkQueue *q)//判队空 { if(q->front == q->rear) return 1; else return 0; } int Out_LQueue(LinkQueue *q, ElemType *license)//出队 { Road *p; if(IsEmpty_LQueue(q)) { printf(”队空“); return 0; } else { p = q->front->next; q->front->next = p->next; *license = p->license; free(p); if(q->front->next == NULL) q->rear = q->front; return 1; } } void main() { ElemType license, time,timelast=0; //timeInlast是最近一次有车进停车场的时间,提示以后输入的进场时间要大于此数值 char command;//进入A还是离开D Parking *s; Backup *s1; LinkQueue *q; PrintInformation1();//输出程序信息和个人信息 s = Init_Parking();//停车场 q = Init_LQueue();//便道队列 s1 = Init_Backup();//退车时的备用栈 printf(”请输入停车每小时需交纳的费用(元)rn“); setbuf(stdin, NULL);//使stdin输入流由默认缓冲区转为无缓冲区,必不可少 scanf(”%d“,&Prize); setbuf(stdin, NULL);//使stdin输入流由默认缓冲区转为无缓冲区,必不可少 while(1) { setbuf(stdin, NULL);//使stdin输入流由默认缓冲区转为无缓冲区,必不可少 Loop:printf(”请输入操作的命令,驶入停车场A,离开停车场D,查看停车场内车数P 0 0,查看候车厂内车数W 0 0,程序结束E 0 0:n“); scanf(”%c%d%d“,&command, &license,&time); setbuf(stdin, NULL);//使stdin输入流由默认缓冲区转为无缓冲区,必不可少 if(command == A) { if(time <= timelast) { printf(”输入的时间必须大于上一次输入的时间:t“); printf(”%dt“, timelast); printf(”请重新输入n“); goto Loop; } else { timelast = time; GetIn(s,q,license,time); } } if(command == D) { if(time <= timelast) { printf(”输入的时间必须大于上一次输入的时间:t“); printf(”%dt“, timelast); printf(”请重新输入n“); goto Loop; } else { timelast = time; GetOut(s, s1, q, license, time);//车开走的函数 } } if(command == P) { if(license == 0 && time == 0) printf(”停车场内停了%d辆车n“,s->top+1);//显示停车场车数 } if(command == W) { if(license == 0 && time == 0) printf(”侯车场内停了%d辆车n“,num);//显示候车场车数 } if(command == E) { if(license == 0 && time == 0) { PrintInformation2();//程序结束信息 system(”pause“); return; } } } } //停车函数 void GetIn(Parking *s, LinkQueue *q,ElemType license, ElemType timeIn) { if(Push_Parking(s, license, timeIn)== 1)//说明成功进入停车场 { printf(”%d号车在%d时刻停在停车场第%d个位置nn“,license,timeIn,s->top+1); } else //栈满,汽车要进入便道,即入队 { num++; In_LQueue(q,license); printf(”%d号车停在候车便道的第%d个位置nn“,license,num); } } void GetOut(Parking *s, Backup *s1,LinkQueue *q, ElemType license, ElemType timeOut) { ElemType *licen, *tim;//两个指针赋给出栈函数,用于读取车牌号和进停车场时间 ElemType ParkTime;//汽车在停车场停留的时间 ElemType Money;//汽车应缴金额 licen =(ElemType*)malloc(sizeof(ElemType)); tim=(ElemType*)malloc(sizeof(ElemType)); if(IsEmpty_Parking(s))//先判断停车场内是否有车 { printf(”对不起!停车场已空!nn“); return; } while(s->license[s->top]!= license) { Pop_Parking(s,licen,tim); Push_Backup(s1, *licen, *tim); if(IsEmpty_Parking(s)==1) { printf(”对不起!停车场内没有车牌号为%d的车nn“,license); while(IsEmpty_Backup(s1)!= 1) { Pop_Backup(s1, licen, tim); Push_Parking(s, *licen, *tim); } return; } } if(s->license[s->top] == license) { ParkTime = timeOut-s->timeIn[s->top]; Money = ParkTime * Prize; printf(”汽车在停车场内停留的时间为%d小时,应缴费%d元nn“,ParkTime,Money); Pop_Parking(s, licen, tim); while(IsEmpty_Backup(s1)!= 1) { Pop_Backup(s1,licen,tim); Push_Parking(s,*licen,*tim); } if(IsEmpty_LQueue(q)!= 1) { Out_LQueue(q,licen); Push_Parking(s,*licen,timeOut); printf(”%d号汽车此时退出便道,进入停车场最后一个位置nn“,*licen); num--; } } } 实验三、管道铺设施工的最佳方案问题 #include ”stdio.h“ #include ”stdlib.h“ #include ”time.h“ #define MaxVertexNum 100 //设置小区数最多为100 #define VertexNum 9 double LeastNum;//用于记录最短边长度 double LongestNum;//用于记录最长边长度,程序过程中不改变 double adjacent[VertexNum][VertexNum]; //邻接矩阵,不用于处理数据,而是用于暂时存储从文件读来的数据 //进而在邻接表存储数据时读取此数组数据即可 //二维数组数据为0的元素说明之间没有通道 //在处理完数据后,此数组会用来暂时存储处理后的数据,并写入到另一个文件中 typedef struct node {//边表结点 char adjvex; double weight;//权值 struct node *next; }EdgeNode; typedef struct vnode {//顶点表结点 char vertex; EdgeNode *firstedge; }VertexNode; typedef struct { VertexNode adjlist[MaxVertexNum]; int n,e; }ALGraph; void PrintInformation1();//输出程序信息和个人信息 void PrintInformation2();//程序结束信息 void CreateALGraph(ALGraph *);//将文件中数据导入进来构建无向图邻接表 void MinimumSpanningTree(ALGraph *);//将无向图转化为最小生成树 void ResultOutput(double *array,int n1,int n2);//将数据在控制台显示出来 void read_data(void);//从输入文件读取数据到邻接矩阵 void cout_data(void);//将邻接矩阵中的数据输出到输出文件 void read_array(double *array,int n1,int n2,FILE *fp);//内部函数,用户无需调用 void cout_array(double *array,int n1,int n2,FILE *fp);//内部函数,用户无需调用 void main() { ALGraph *G; PrintInformation1(); G =(ALGraph*)malloc(sizeof(ALGraph)); G->n = VertexNum;//为G指向的图分配空间,设置点数(小区数) read_data(); CreateALGraph(G); MinimumSpanningTree(G); cout_data();//输出到文件 ResultOutput((double *)adjacent,VertexNum,VertexNum);//输出到控制台 PrintInformation2(); system(”pause“); } void PrintTime() { time_t t; time(&t); printf(”%s“, ctime(&t)); printf(”rn“); } void PrintInformation1() { printf(”实验名称:实验三.管道铺设施工的最佳方案问题rn“); printf(”学号:031650106rn“); printf(”姓名:郭砚璞rn“); printf(”====================rn“); printf(”程序运行开始,Current local time and date:“); PrintTime(); } void PrintInformation2() { printf(”rn====================rn“); printf(”程序运行结束,Current local time and date:“); PrintTime(); } void CreateALGraph(ALGraph *G) { //建立无向图的邻接表存储 int i=0,j=0,k=0; EdgeNode *s; for(i = 0;i < G->n;i++) { G->adjlist[i].vertex = 65 + i; printf(”t%c“,(G->adjlist[i].vertex));//控制台输出列表头 G->adjlist[i].firstedge=NULL; } printf(”n“); for(k=0;k { for(j=0;j { if(adjacent[k][j]!=0) { s =(EdgeNode*)malloc(sizeof(EdgeNode)); s->adjvex = 65+j; s->weight=adjacent[k][j]; s->next = G->adjlist[k].firstedge; G->adjlist[k].firstedge = s; } } } } void read_data(void) { int i,j; FILE *fp; fp=fopen(”gyp_program3_Input.dat“,”r“);// 输入数据文件 read_array((double *)adjacent,VertexNum,VertexNum,fp); fclose(fp); for(i = 0;i < VertexNum;i++) { for(j = 0;j < VertexNum;j++) { if(adjacent[i][j] > LongestNum) { LongestNum = adjacent[i][j];//即给LongestNum设置的初值为最大边边值 } } } } void read_array(double *array,int n1,int n2,FILE *fp) { int i,j; float q; for(i=0;i for(j=0;j { fscanf(fp,”%f“,&q); *array++ =(double)q; } } void cout_data(void) { FILE *fp; fp=fopen(”gyp_program3_Output.dat“,”w“);//输出数据文件 cout_array((double *)adjacent,VertexNum,VertexNum,fp); fclose(fp); } void cout_array(double *array,int n1,int n2,FILE *fp) { int i,j; for(i = 0;i < n2;i++) { fprintf(fp, ”t%c“, 65 + i);//输出文件里打印列表头 } fprintf(fp,”n“); for(i=0;i { fprintf(fp,”%ct“,65+i);//输出文件里打印行表头 for(j=0;j { fprintf(fp,”%.1ft“,*array); array++; } fprintf(fp,”n“); } } void ResultOutput(double *array,int n1,int n2) { int i,j; for(i=0;i { printf(”%ct“,65+i);//控制台输出行表头 for(j=0;j { printf(”%.1ft“,*array); array++; } printf(”n“); } } void MinimumSpanningTree(ALGraph *G) {//将无向图转化为最小生成树 int i, j, k; int flag2=1,point; int start, end; EdgeNode *s; char NowAdjacent[VertexNum]; for(i=0;i { for(j = 0;j < VertexNum;j++) { adjacent[i][j] = 0;//先将邻接矩阵所有值清零 } } NowAdjacent[0]=G->adjlist[0].vertex;//初始点放入点集 for(i=0;i //刚开始只有一个起始点,之后加入剩余的VertexNum个点,即VertexNum-1次循环 { LeastNum = LongestNum;//这一步很重要,每加入一个点,应把LeastNum初始化为//最大值,避免受之前数值的影响 for(j = 0;j < i + 1;j++)//第i次点集里有i+1个点,即比较这i+1个点与生于点边的大//小,找最小边的另一个点 { point = NowAdjacent[j]-A;//用于指示已经存进点集中的点是图的第几个点 s = G->adjlist[point].firstedge; while(s!= NULL) { for(k = 0;k < i + 1;k++) { if(s->adjvex == NowAdjacent[k]) { flag2 = 0;//flag2=0用于指示此时s所指的点已经在点集内 break; } } if(flag2 == 1)//确保仅当s指向的点是不在点集里的点时,才被比较处理 { if((LeastNum > s->weight)&&(s->weight!=0)) { end = s->adjvex-A;//flag用于指示最短边是第几个点 start = point; LeastNum = s->weight; } } s = s->next; flag2 = 1;//标志位有可能已经被清0,必须重设为1,确保不影响下一次 } //启发:对于用的不止一次的标志位,一定不可能只单方向置位,一定是双向置位,//否则用了一次,后面就会误判 } adjacent[start][end] = LeastNum; adjacent[end][start] = LeastNum; NowAdjacent[i + 1] = G->adjlist[end].vertex;//向点集加入新点 } } 实验四、内部排序算法的实现与比较 #include ”stdio.h“ #include ”stdlib.h“ #include ”time.h“ const int N=3000;//随机产生N个随机整数 void PrintInformation1();//输出程序信息和个人信息 void PrintInformation2();//程序结束信息 void PrintTime(); void InsertSort(int R[], int n);//插入排序 void SelectSort(int R[], int n);//选择排序 void BubbleSort(int R[], int n);//冒泡排序 void QuickSort(int R[],int low,int high);//快速排序 void ShellInsert(int R[],int m,int n);//快速排序 void Shellsort(int R[],int n);//希尔排序 void KeyCompareNum_pailie(); void MoveNum_pailie(); int KeyCompareNum[5]={0};//分别存储这5种排序的关键字比较次数 int MoveNum[5]={0};//分别存储这5种排序的移动次数 int main() { //数组设为N+1个是因为有些算法是从数组1到N存储的,0位有的不用,有的用作了哨兵 int num0[N+1];//记录最原先随机产生的N个数字,因为num[N]每排序一次都会改变 int num[N+1];//每次排序前先读入num0[N]数据 //srand函数只增加一次就够了,用系统当前时间设置rand()随机序列种子,保证每次运行随机序列不一样 srand((unsigned)(time(NULL))); for(int j = 0;j < N;j++) { num0[j] = rand(); } PrintInformation1(); for(int j=0;j { num[j] = num0[j]; } InsertSort(num,N); for(int j = 0;j < N;j++) { num[j] = num0[j]; } SelectSort(num,N); for(int j = 0;j < N;j++) { num[j] = num0[j]; } BubbleSort(num,N); for(int j = 0;j < N;j++) { num[j] = num0[j]; } Shellsort(num,N); for(int j = 0;j < N;j++) { num[j] = num0[j]; } QuickSort(num,0,N-1); printf(”关键字比较次数按从小到大排列分别是:rn“); KeyCompareNum_pailie(); printf(”rn“); printf(”移动次数按从小到大排列分别是:rn“); MoveNum_pailie(); PrintInformation2(); system(”pause“); return 0; } void KeyCompareNum_pailie()//关键字比较次数排列 { int i,j,k,m; int printnum=0;//用于记录上一次输出的是数组KeyCompareNum的第几个数 int minimum;//用于输出最小的数字 int maximum=0; for(i = 0;i < 5;i++) { if(maximum < KeyCompareNum[i]) maximum = KeyCompareNum[i]; } for(m = 0;m< 5;m++) { minimum = maximum; //minimum在每次输出是都是全新的,不能受之前数值的影响,因此每次输出第一步先//把minimum设为最大值 for(j = 0;j < 5;j++) { if((minimum >=KeyCompareNum[j])&&(KeyCompareNum[j]!= 0)) { minimum = KeyCompareNum[j]; } } for(k = 0;k < 5;k++)//编程时k原先用的还是i,结果i=4这个情况,break以后到紧接//着的外层循环时,i的数值影响到了外层循环,跳了出来,因此换成了k { if(minimum == KeyCompareNum[k]) { KeyCompareNum[k] = 0; printnum = k; break; } } if(printnum == 0) printf(”直接插入排序:%dt“, minimum); if(printnum == 1) printf(”选择排序:%dt“,minimum); if(printnum == 2) printf(”冒泡排序:%dt“, minimum); if(printnum == 3) printf(”快速排序:%dt“, minimum); if(printnum == 4) printf(”希尔排序:%dt“, minimum); } printf(”rn“); } void MoveNum_pailie()//移动次数排列 { int i, j, k, m; int printnum = 0;//用于记录上一次输出的是数组KeyCompareNum的第几个数 int minimum;//用于输出最小的数字 int maximum = 0; for(i = 0;i < 5;i++) { if(maximum < MoveNum[i]) maximum = MoveNum[i]; } for(m = 0;m < 5;m++) { minimum = maximum;//minimum每次输出是都是全新的,不能受之前数值的影响,//因此每次输出第一步先把minimum设为最大值 for(j = 0;j < 5;j++) { if((minimum >= MoveNum[j])&&(MoveNum[j]!= 0)) { minimum = MoveNum[j]; } } for(k = 0;k < 5;k++)//编程时k原先用的还是i,结果i=4这个情况,break以后到紧接//着的外层循环时,i的数值影响到了外层循环,跳了出来 {//因此换成了k if(minimum == MoveNum[k]) { MoveNum[k] = 0; printnum = k; break; } } if(printnum == 0) printf(”直接插入排序:%dt“, minimum); if(printnum == 1) printf(”选择排序:%dt“, minimum); if(printnum == 2) printf(”冒泡排序:%dt“, minimum); if(printnum == 3) printf(”快速排序:%dt“, minimum); if(printnum == 4) printf(”希尔排序:%dt“, minimum); } printf(”rn“); } void InsertSort(int R[], int n)//插入排序 { int i, j; for(i = 2;i <= n;i++) { R[0] = R[i]; MoveNum[0]++; j = i-1; while(R[0] < R[j]) { KeyCompareNum[0]++; R[j + 1] = R[j]; MoveNum[0]++; j--; } R[j + 1] = R[0]; MoveNum[0]++; } } void SelectSort(int R[], int n)//选择排序 { int i, j, k; for(i = 1;i < n;i++) { k = i; for(j = i + 1;j <= n;j++) if(R[j] < R[k]) { k = j; KeyCompareNum[1]++; } if(k!= i) { R[0] = R[k]; R[k] = R[i]; R[i] = R[0]; MoveNum[1]+=3; } } } void BubbleSort(int R[], int n)//冒泡排序 { int i, j, flag = 0; for(i = 1;(i < n && flag == 0);i++) { flag = 1; for(j=1;j if(R[j + 1] < R[j]) { KeyCompareNum[2]++; flag = 0; R[0] = R[j]; R[j] = R[j+1]; R[j + 1] = R[0]; MoveNum[2]+=3; } } } void QuickSort(int R[],int low,int high)//快速排序 { int i,j; i=low; j=high; R[0]=R[i]; MoveNum[3]++; while(i { while((R[j]>=R[0])&&(j>i)) { j--; KeyCompareNum[3]++; } if(j>i) { R[i]=R[j]; MoveNum[3]++; i++; } while((R[i]<=r[0])&&(j>i)) { i++; KeyCompareNum[3]++; } if(j>i) { R[j]=R[i]; MoveNum[3]++; j--; } } R[i]=R[0]; MoveNum[3]++; if(low QuickSort(R,low,i-1); if(i QuickSort(R,j+1,high); } void ShellInsert(int R[],int m,int n) {//一趟希尔排序,按间隔m划分子序列 int temp,j; for(int i=m;i { temp=R[i]; MoveNum[4]++; j=i; while(j>=m && temp { KeyCompareNum[4]++; R[j]=R[j-m]; MoveNum[4]++; j-=m; } R[j]=temp; MoveNum[4]++; } } void Shellsort(int R[],int n)//希尔排序 { int m; m=n/2; while(m>=1) { ShellInsert(R,m,n); m=(m==2?1:(m/2)); } } void PrintTime() { time_t t; time(&t); printf(”%s“, ctime(&t)); printf(”rn“); } void PrintInformation1() { printf(”实验名称:实验四.内部排序算法的实现与比较rn“); printf(”学号:031650106rn“); printf(”姓名:郭砚璞rn“); printf(”====================rn“); printf(”程序运行开始,Current local time and date:“); PrintTime(); } void PrintInformation2() { printf(”rn====================rn“); printf(”程序运行结束,Current local time and date:"); PrintTime(); 【计算机实验心得体会】推荐阅读: 计算机实验课实验报告10-29 《计算机导论》实验报告05-23 计算机科学导论实验10-13 计算机基础实验任务一07-17 计算机基础课程实验报告11-09 计算机网络基础实验一09-25 计算机基础实验报告单(例文)09-12 云计算实验报告01-22 喷泉实验的计算03-09 大学计算机基础第一次实验报告作业11-13