20172304 2018-2019-1 实验一博客
- 课程:程序设计与数据结构
- 班级:1723
- 姓名:段志轩
- 学号:20172304
- 实验老师:王志强
- 助教:张之睿和张师瑜
- 选修/必修:必修
实验要求
- 实验1
链表练习,要求实现下列功能:
(1)通过键盘输入一些整数,建立一个链表(1分);
这些数是你学号中依次取出的两位数。 再加上今天的时间。
例如你的学号是 20172301
今天时间是 2018/10/1, 16:23:49秒
数字就是
20, 17,23,1, 20, 18,10,1,16,23,49
打印所有链表元素, 并输出元素的总数。
在你的程序中,请用一个特殊变量名来纪录元素的总数,变量名就是你的名字。 例如你叫 张三, 那么这个变量名就是
int nZhangSan = 0; //初始化为 0.
做完这一步,把你的程序签入源代码控制(git push)。
- 实验2
链表练习,要求实现下列功能:
(2)实现节点插入、删除、输出操作(2分,3个知识点根据实际情况酌情扣分);
继续你上一个程序, 扩展它的功能,每做完一个新功能,或者写了超过10行新代码,就签入代码,提交到源代码服务器;
从磁盘读取一个文件, 这个文件有两个数字。
从文件中读入数字1, 插入到链表第 5 位,并打印所有数字,和元素的总数。 保留这个链表,继续下面的操作。
从文件中读入数字2, 插入到链表第 0 位,并打印所有数字,和元素的总数。 保留这个链表,并继续下面的操作。
从链表中删除刚才的数字1. 并打印所有数字和元素的总数。
签入所有代码。
- 实验3
链表练习,要求实现下列功能:
(3)使用冒泡排序法或者选择排序法根据数值大小对链表进行排序(2分);
如果你学号是单数, 选择冒泡排序, 否则选择选择排序。
在排序的每一个轮次中, 打印元素的总数,和目前链表的所有元素。
在(2)得到的程序中继续扩展, 用同一个程序文件,写不同的函数来实现这个功能。 仍然用 nZhangSan (你的名字)来表示元素的总数。
- 实验4
数组练习,要求实现下列功能:
(1)通过键盘输入一些整数,建立一个链表(1分);
这些数是你学号中依次取出的两位数。 再加上今天的时间。
例如你的学号是 20172301
今天时间是 2018/10/1, 16:23:49秒
数字就是
20, 17,23,1, 20, 18,10,1,16,23,49
打印所有数组元素, 并输出元素的总数。
在你的程序中,请用一个特殊变量名来纪录元素的总数,变量名就是你的名字。 例如你叫 张三, 那么这个变量名就是
int nZhangSan = 0; //初始化为 0.
做完这一步,把你的程序签入源代码控制(git push)。
(2)实现节点插入、删除、输出操作(2分,3个知识点根据实际情况酌情扣分);
继续你上一个程序, 扩展它的功能,每做完一个新功能,或者写了超过10行新代码,就签入代码,提交到源代码服务器;
从磁盘读取一个文件, 这个文件有两个数字。
从文件中读入数字1, 插入到数组第 5 位,并打印所有数字,和元素的总数。 保留这个数组,继续下面的操作。
从文件中读入数字2, 插入到数组第 0 位,并打印所有数字,和元素的总数。 保留这个数组,并继续下面的操作。
从数组中删除刚才的数字1. 并打印所有数字和元素的总数。
签入所有代码。
- 实验5
数组练习,要求实现下列功能:
(3)使用冒泡排序法或者选择排序法根据数值大小对数组进行排序(2分);
如果你学号是单数, 选择选择排序, 否则选择冒泡排序。
在排序的每一个轮次中, 打印元素的总数,和目前数组的所有元素。
在(2)得到的程序中继续扩展, 用同一个程序文件,写不同的函数来实现这个功能。 仍然用 nZhangSan (你的名字)来表示元素的总数。
实验思路以及实现过程
- 实验1:实验一要求的是通过键盘输入建立一个链表,然而老师并没说不可以用插入的方法,于是在实验一中我先行实现了链表的尾插法和打印方法。先通过Scanne类读取通过键盘输入的数据,然后通过StringTokenizer类将输入的数据通过分隔符来进行分割,最后利用循环和链表的插入方法进行链表的创建。除此之外还需要进行总数的统计,所以我就在方法类中定义了一个整数型变量nDuanZhixuan,然后还创建了一个统计总数的方法。
- 这是声明的Scannner类以及使用Scanner类进行读取的截图。
- 这是使用StringTokenier类进行分割以及循环插入的截图。
- 这是实现尾插法的截图。具体思路为先创造一个类这个类的构造函数中声明了一个空的引用变量next以及一个int型变量的空间。然后使用指针指向下一个被插入的节点,以此往复。这个类的截图我也会在下面进行给出。
这是尾插法的截图
这是结点类的截图
- 这是实现打印的方法的截图。这个具体的就不想解释,但还是要说一说,主要就是通过一个while循环,在节点不为空时将其中储存的int性变量提取出来然后,储存在一个String型变量中最后进行输出。
- 这是实现统计元素总量的方法,主要就是通过定义一个变量对头结点进行引用,然后通过循环遍历整个链表,同时在循环中对nDuanZhixaun变量进行自加运算,从而达到统计元素总量的目的。
- 测试类代码截图以及测试结果截图。
- 实验二
在实验二中我着重于实现按照索引插入,按索引删除,按元素搜索删除的方法。由于输出操作在实验一中就已经进行了,所以此时就不再赘言。着重介绍按索引插入,按索引删除,按元素搜索删除。至于文件读写的具体操作就不讲了,主要介绍读取文件的方法。 - 按索引插入
主要思路:首先考虑一下按索引插入的情况共分三种:从头插入,从尾插入,还有从中间插入。
用if条件语句判断如果首节点为空,在头节点插入,直接令头结点为传入数据的节点。如果头结点不为空,就令新引入的节点的指针指向头结点,然后将引入的节点声明为头结点。从中间插入,我则使用了两个变量,一个引用头结点,另一个引用头结点的下一个节点。然后使用for循环,令两个节点进行遍历至输入索引对应的节点处。两个节点分别表示带插入节点的前后节点。然后用前节点的指针指向新插入的节点,用新插入的节点的指针指向后节点。
上截图
- 按索引删除
主要思路:首先考虑到了首先要找到要删除的节点,通过循环进行遍历同样先定义前后节点等到找到要删除的节点时,然后使用前节点的指针指向后节点。
上截图
- 按搜索元素删除
主要思路:通过遍历查找传入元素所对应的节点同时遍历前后节点,然后将前节点的指针指向后节点。
上截图
- 文件读取
主要思路:这个我可以详细解释一下。首先声明一个File形变量,并向构造函数中传入需要读取文件的绝对路径(即从磁盘到文件夹到文件),以获得文件的位置,然后使用Reader类读取文件内容,然后使用BufferReader将文件内容存放在缓冲区。最后使用BufferReader类的readLine方法读取文件。
上截图
测试结果截图
- 实验三
进行排序由于我的学号是20172304,显然这是一个偶数,显然交给我的任务是选择排序,选择排序的方法我有点生疏就上网上查阅了一下,为了证明自己已经懂了,决定要详细的说明一下,首先要做嵌套循环,外循环遍历整个链表,内循环,从外循环所在的节点,遍历整个链表,并对节点储存的数据进行比较,如果大于外循环所在的节点,则交换数据之。由于要求进行输出元素总数,所以我在每次内循环结束时都调用了一次链表的打印方法。
上截图
测试结果截图
- 实验四
实验四的第一步就没有什么好说的了,就是创建一个数组,然后用Scanner类读取,然后用StringTokenizer进行分割然后使用StringTokenizer类自带的方法hasMoreTokens进行循环,然后使用nextToken的方法将输入的字符串存入数组中。打印数组的方法我就不想加截图了,主要就是通过循环遍历曾哥
上截图
然后第二步文件的读写和链表的相似,就不在赘言,主要介绍删除,插入和打印的方法。删除我做了两个,一个是按索引删除,另一个是按照搜索元素删除。 - 按索引插入
主要思路:首先在方法内定义一个数组。然后将索引处的数据以及索引后数组内的数据通过循环存入新数组中,最后通过循环将新数组内的元素添加到原有的数组中。当然首先要检查数组是否已满,如果已满就要进行扩容。我写了一个扩容的方法。就是定义一个新数组是原有数组的容量的两倍。然后通过循环将原有数组的元素复制到新数组对应的位置上。
上截图
这是索引插入的截图
扩容的方法截图
- 按索引删除
主要思路:通过循环遍历到索引对应的数组的位置所储存的数值,然后将索引后的元素通过循环复制到新创建的数组对应位置,然后通过循环将新创建的数组的元素复制到原数组中。
上截图
- 搜索元素进行删除
主要思路:做这个的时候我就有点偷懒了,通过遍历找到传入元素所在的索引值,然后调用之前写的按照索引删除的方法,你懂的‘’‘’‘’‘。
上截图
测试结果截图
- 实验五
进行选择排序,原理和链表相似。同样是进行嵌套循环,然后外循环对整个数组有元素的部分进行遍历,然后内循环在外循环索引的基础上进行循环,遇到比外循环索引对应的元素小的元素就进行交换。同时在进行内循环一次是就将整个数组进行输出。
上截图
测试结果截图
本次实现代码的码云链接
实验中遇见的问题以及解决方案
- 问题一:
在实验一中,有一步是将用户传进来的数据通过StringTokenizer类进行分割。这时要进行一步操作就是将数据存入链表节点中,如下图,节点中储存的数据类型是int型
然而,用StringTokenizer分割出来的数据是实打实的String类型,所以一开始想用int来进行强转。但是报错。
问题一解决方案:后来咨询了同学
XX:“String转int怎么转来着?”
XXX:“好像是用Integer什么来着。”
感谢万能的IDEA,当我输入"Integer."就立即显示出了“paseInt(String s)”的字样,然后就顺理成章的成功了。只要进行一次装箱,拆箱的操作,借助中间媒介,就可以将String转Int了。
- 问题二
在进行文件读取时会发现有异常。如截图。 - 问题二解决方案
这个,说了也许你可能不信,当时我进行了如下操作,那时并没有多想。
第一步:在java中右击新创建的文本文件。
然后点击“Copy Path”,然后复制到Flie类的构造函数的括号里。
然后我就知道了,这一步需要的是绝对路径。
还有一些问题由于当时忘记截图,所以准备采用口述的方式。
- 问题三:在进行数组的插入方法时,一开始我的脑子秀逗了,想的是用数组本身进行自循环,即类似于
for(tnt b=index;b<nDuanZhixaun//数组的元素数量 ;b++)
a[b+1]=a[b]
这段代码来解决,但是这个方法过于简单粗暴,回馈给我的就是在索引值后面,会有一堆重复 的数字,当时我还记得那些数字是一堆“5”。
- 问题三解决方案:首先分析错误类型,这应该是个逻辑错误,那就从逻辑上分析。分析中.......分析完毕。分析结果是,应该有个缓冲。所以我写了如下代码,添加了一个用于缓冲的数组。
int []c=new int[a.length];
int d=0;
int f=0;
for(int b=index;b<nDuanZhixuan;b++)
{
c[b]=a[b];
d++;
}
这样我成功的解决了这个问题。
实验感想
本次实验是对前面所学知识的一个总结,通过这次实验,我对曾经学过的知识有了更深一步的了解同时对一些类的应用也更加熟悉,同时也弄懂了一些过去不是很懂的知识点可谓是受益匪浅。正所谓“温故而知新,可以为师矣”正是此理。