课程:《程序设计与数据结构》
班级: 1723
姓名: 王禹涵
学号: 20172323
实验教师:王志强老师
测试日期:2018年9月
必修/选修: 必修php
链表练习,要求实现下列功能:
(1)经过键盘输入一些整数,创建一个链表;
(2)实现节点插入、删除、输出操做;
(3)使用冒泡排序法或者选择排序法根据数值大小对链表进行排序;前端
错误的示范:
最开始的思路是借助上学期曾完成的一个代码,它实现了一个以整形数为结点的链表,并实现了选择排序的功能,因此我想就在这串代码的基础之上完成。
首先研究的是它已提供的几个方法
addjava
public void add(Number num) { NumberNode node = new NumberNode(num); NumberNode current; if (list == null) { list = node; } else { current = list; while (current.next != null) { current = current.next; } current.next = node; } }
这里的add方法至关因而栈里的Push而不是咱们所须要实现的插入的方法,这里是我犯的第一个错误了。把输入整数建立一个链表与在链表中插入整数混为一谈。
但这串代码提供了输入整数建立链表的功能,我借助上学期用过的一个方法,将用户输入的一串数字经过空格间隔开,再用Integer.parseInt
的方法从新将字符转化为int型,再经过add的方法存入链表。具体的代码以下node
LinkedList a = new LinkedList(); Scanner scan = new Scanner(System.in); System.out.println("Input some numbers into the linkedlist: "); String b = scan.nextLine(); StringTokenizer NUM = new StringTokenizer(b, " "); while (NUM.hasMoreTokens()){ a.add(Integer.parseInt(NUM.nextToken())); }
能够说是很是的麻烦了。
这时又得从新编写一个插入的方法,既然是要能实如今指定位置的地方插入元素,因而我想到了运用for循环来完成,又由于插入位置的不一样分红了两种状况:头插法以及在中间或尾部插入元素。代码以下git
public NumNode InsertNode(int num, int a) { NumNode Head = list; NumNode node = new NumNode(num); if (a == 1){ node.next = Head; Head = node; } else { NumNode temp = Head; for (int n = 0; n < a - 2; n++){ temp = temp.next; } if (temp.next == null){ temp.next = node; } else { NumNode node1 = temp.next; temp.next = node; node.next = node1; } } return Head; }
测试类的代码不放在上面,但最终运行的结果出现了问题。虽然在中部和尾部插入没有出现问题,但在头部的插入出现了问题,在执行插入操做以后,最终显示的结果并无插入成功。如图
web
最后经过debug的调试发如今编写的类中虽然有return Head,但测试类中并无语句使得Head的值return到链表里。解决的方法就是将链表a再赋给a一次,如a = a.InsertNode(c,d);
(c是要插入的数,d是要插入的位置),但仍是会报错,缘由在于类型的不兼容,如图
数据结构
一边a的定义是LinkedList类型,一边又要调用NumNode的方法。因此方法最终是不可行的。测试
成功的解决
最终我想选择运用哑结点的方法来解决头插法的插入问题。this
经过在列表的前端引入哨兵结点或哑结点,能够去除涉及第一个结点的状况。哨兵结点能够做为一个假的第一个结点,并无真正表示列表中的某个元素。当使用了哨兵结点时,全部的插入和删除操做都不用考虑太多特殊状况。debug
一开始我是想真的设置一个哨兵结点,即不在里面放数字,仅有next的方法连接真正的链表。但设置Numnode head1 = null
或者Numnode head1 = ""
彷佛并不能使head1成为空结点,Numnode定义里要求必须插入一个数字,因此最后就只有将就着设置一个假的哑结点Numnode head1 = new Numnode(0)
,而后很机智的在toString方法里修改一下,不显示第一个结点就能够了。
public String toString() { String result = ""; NumNode current = head1.next; while (current != null) { result += current.number + " "; current = current.next; } return result; }
toString方法:这里就设置了一下,使得显示的时候从head1的下一个head1.next
开始。
private class NumNode{ public int number; public NumNode next; public NumNode(int number) { this.number = number; next = null; } }
Numnode方法:定义告终点的方法,包括一个int型number,和指向下一结点的next。
public void InsertNode(int num, int a) { head1.next = list; NumNode node = new NumNode(num); NumNode temp = head1; for (int x = 0; x < a - 1; x++){ temp = temp.next; } if (temp.next == null){ temp.next = node; } else { NumNode node1 = temp.next; temp.next = node; node.next = node1; } }
InsertNode方法:num表示要插入的数字,a表示要插入的位置。先将num放入一个无连接的元素node,用for循环找到要插入的位置以后,再将前一个位置的next指针指向node,再将node的next指向下一个指针。
若是是直接在链表的末端插入的话就是上文提到的add方法了。我编写的代码里有一点小的缺陷就是,没有将插入和添加的方法分得很开,若是故意用插入的方法将元素添加到链表末尾应该是会报错的吧,由于node的next指针不能指向下一结点。
public void delete(int k){ head1.next = list; NumNode PreNode = null, Currentnode = head1; for (int x = 0; x < k - 1; x++){ if (Currentnode.next != null){ PreNode = Currentnode; Currentnode = Currentnode.next; PreNode.next = Currentnode.next; } else{ PreNode = Currentnode; PreNode.next = null; } } }
delete方法:删除的代码实现本质上与插入相差无异,插入的编好删除也完成了一大半了。
public void sort() { NumNode min; int temp; NumNode numNode = list; while (numNode != null) { min = numNode; NumNode current = min.next; while (current!=null) { if(Integer.parseInt(String.valueOf(min.number)) > Integer.parseInt(String.valueOf(current.number))) { min = current ; } current = current.next; } temp = min.number; min.number = numNode.number; numNode.number = temp; numNode = numNode.next; } }
sort方法:排序的方法是借鉴的上学期的选择排序法,这大概是惟一没碰见问题的地方。
node.next = Head
,Head = node
,return Head
,但最后toString并无显示头插法的结果。a = a.InsertNode(c,d);
,但在这串代码里InsertNode是Numnode的方法,而a是LinkedList型,因此二者类型不兼容,不一样类型的值的赋值会报错原本是想这学期每一个测试都能好好作,一篇博客也不要补,即使是本身作的不好劲也不要补博客。嗯...真香 测试实际上是有在好好作,奈何读题太快,完成做业的心态也比较浮躁,致使最后并无好的结果,因此不得不认认真真地再补一篇博客。一开始仍是抱着想快点了事的心态在作,因此很快就把前半部分写了出来,后来补代码遇到瓶颈再仔细审题我才眉头一皱发现事情并不简单,特别是涉及到头结点的问题真是费脑筋,上面的只是一小部分个人记录,真实状况远比这复杂得多,一个星期里我既抱着个人代码不放,不想就此打水漂,但问题又始终解决不了,另外一方面我借鉴了数十个同窗的代码,发现多多少少都有一些问题,想借此蒙混过关几乎不可能。 因此最后献上的代码绝对使我绞尽脑汁想了好久好久才写出来的解决方法,万望学长学姐多给点分。