数据结构:老是为了完成一个功能或者目的写程序,但无论什么程序、代码实际上都是一些指令的集合,说白了就是在描述“怎么作”,而光知道怎么作还只是问题的一半,还要知道“作什么”,也就是刚才那些指令的对象是谁,天然确定是相关的数据,好比说学生信息管理中,指令是增长学生,那他的对象就是学生信息这种数据,指令是成绩统计,那对象就是学生的成绩数据,而在咱们的程序中,数据也必需要有一种很明确的组织表示方式,只要这样咱们才能在这种具体明确的实体上编写指令,好比说学生数据能够定义为一个多维的数组,只有这样咱们再写增长学生时,才能知道具体增长就是增长一个数组元素并为其赋值。因此数据结构就是相互之间有联系的具备某种组织方式的数据集合。php
抽象数据类型相比较数据结构要具体一些,咱们光有了数据结构还不够,由于数据是各类各样的,对于不一样数据,咱们能采起的方法也不同,好比说学生数据能够增减,成绩数据能够进行算数运算,可是为何说抽象呢,也就说他并非具体整型仍是字符型这种基本类型,而是咱们根据咱们要解决的实际问题,对应现实世界所描述的一种和现实世界中的实体对应的数据类型,并且这种抽象的数据类型还包括可以对于他实行的操做,好比说咱们定义一种数据类型叫“学生”,具体的数据我能够定义一中相似表的结构存储,并且还要定义一些操做,好比说添加学生,删除学生,这两部分就共同组成了“学生”这个抽象的数据类型。html
1.向链表中添加元素。判断一个链表已经到达末尾的依据是该结点的next引用已经为Null,因此要向末尾添加一个结点,先要把新增结点放在最后,再把末尾结点向后移位,具体操做过程以下图:
java
代码以下:node
/** * 向指定链表添加元素的方法 * @param obj 插入的元素 */ public void add(Object obj){ Node node=new Node(obj);//新建结点 if(head==null){//若是链表为空 head = node; }else{ last.next=node;//先把新增结点放在最后 } last=node;//再把最后一个结点向后移位 }
2.插入元素。要插入一个新元素首先要建立一个新结点来存放它,而在具体实现的时候最让人头疼的时候无疑是怎样找到指定位置的索引了,这里所说的方法在下面的其余操做基本上都是这样衍生的,先了解一下插入结点的具体实现,根据这个结构的逻辑定义,若是咱们要在结点A以后插入一个结点,那么就还须要修改结点A的next引用,实际上就是让A结点的next引用指向新增结点的元素域,而后再让新增结点的next引用指向A本来next结点(B)的元素域,用图来表示更加直观:git
代码以下:web
/** * 向链表中插入新元素的方法 */ public void insert(int index,Object obj){ Node node=head; int j=0; while(node!=null&&j<index-2){ //查找到第index-1个元素 node=node.next; j++; } Node sert=new Node(obj);//被插入的结点 sert.next=node.next; node.next=sert; }
3.删除元素。知道了插入元素的具体操做以后,删除元素就显得相对简单了,好比说咱们要删除一个结点b,就是要使这个结点失去引用,可是注意不要直接写b=b.next,这样的话b的引用仍是存在,并且还会出现另外一种错误,如图所示,正确的删除结点的方法以下:
数组
代码以下:数据结构
/** * 删除指定位置的结点 * @param index 索引 */ public void delete(int index){ Node node=head; int j=0; while(node!=null&&j<index-2){ //查找到第i-1个元素 node=node.next; j++; } node.next=node.next.next;//删除第index个元素 }
4.最后就是修改元素了。
代码以下:函数
/** * 改变指定位置的元素 * @param index 索引 * @param obj */ public void modify(int index,Object obj){ Node node=head; int j=0; while(node!=null&&j<index-1){ //找到第index个结点 node=node.next; j++; } node.obj=obj; }
单链表(单向链表):由两部分组成 数据域(Data)和结点域(Node),单链表就像是一条打了不少结的绳子,每个绳结至关于一个结点,每一个节结点间都有绳子链接,这样原理的实现是经过Node结点区的头指针head实现的,每一个结点都有一个指针,每一个节点指针的指向都是指向自身结点的下一个结点,最后一个结点的head指向为null,这样一来就连成了上述所说绳子同样的链,对单链表的操做只能从一端开始,若是须要查找链表中的某一个结点,则须要从头开始进行遍历。
学习
双链表(双向链表):双链表和单链表相比,多了一个指向尾指针(tail),双链表的每一个结点都有一个头指针head和尾指针tail,双链表相比单链表更容易操做,双链表结点的首结点的head指向为null,tail指向下一个节点的tail;尾结点的head指向前一个结点的head,tail 指向为null,是双向的关系;
双向链表的节点类代码:
public class Node { //存储的数据 private Object data; //前一个节点 private Node prev; //后一个节点 private Node next; public Object getData() { return data; } public void setData(Object data) { this.data = data; } public Node getPrev() { return prev; } public void setPrev(Node prev) { this.prev = prev; } public Node getNext() { return next; } public void setNext(Node next) { this.next = next; } //定义构造函数 public Node(){ } public Node(Object data, Node prev, Node next) { super(); this.data = data; this.prev = prev; this.next = next; } }
双向链表的部分具体实现代码:
//实现双向链表 public class myDoubleLinkImpl { //记录链表的节点数 int length=0; //定义上一个节点 private Node header; //定义下一个节点 private Node tail; public myDoubleLinkImpl(){ //定义的一个空的链表 header=null; tail=null; length=0; } //获取链表的节点值 public int getLength() { return length; } //向链表中添加值 public void add(Object data) { //判断链表是不是空的哈 if(header==null) { header=new Node(data,null,null); tail=header; length++; }else{ //非空链表哈 Node tempNode=new Node(data,tail,null); tail.setNext(tempNode); tail=tempNode; length++; } }
错误的代码以下:
public void delete(Magazine delNode){ MagazineNode node=new MagazineNode(delNode); MagazineNode current=list; MagazineNode behind=current; if (list==null) list=null; else if (current.magazine.toString().equals(node.toString())) current=current.next; else{ while (!current.next.magazine.toString().equals(node.toString())) { behind.next=current; current=current.next; } current=current.next; behind.next=current.next; list=behind; } }
正确的思路:
单链表的操做:
添加:上图能够看出 单向链表只有一个指向,原来head为p,p指向s,添加结点只须要把p指向q,q指向s就能够了,即:p--->q ; q--->s ; 这样就实现了单向链表的添加;
删除:原理与添加相反,若此时链表为 p---> q --->s ; 若删除q节点只须要更改p的指向就能够了 p--->s,这样就删掉了;
修改以后的正确代码以下:
public void delete(Magazine delNode) { MagazineNode front = list; MagazineNode current = front.next; if (delNode.toString().equals(front.magazine.toString())) list = front.next; else { while (!current.magazine.toString().equals(delNode.toString())) front = front.next; front.next = current.next; } }
import java.util.LinkedList; public class Sorting3 { //----------------------------------------------------------------- // Sorts the specified array of objects using the selection // sort algorithm. //----------------------------------------------------------------- public static void sortLink(LinkedList<Integer> link) { int min; int temp; for (int index = 0; index < link.size() - 1; index++) { min = index; for (int scan = index + 1; scan < link.size(); scan++) { if (link.get(scan).compareTo(link.get(min)) < 0) { min = scan; } } // Swap the values temp = link.get(min); link.set(min, link.get(index)); link.set(index, temp); } } }
测试类的代码及运行截图以下:
错题1
理解:无限循环和递归都是类似的,它们不断地无限重复。编译器或运行时(JVM)都不能捕获它们。
错题2
错因:忽略了输入为0的时候这种特殊状况!!一样输入参数0,第一个return为0,第二个则会陷入无限递归。
错题3
理解:递归和迭代在计算上是等价的——每个均可以被另外一个取代。
。
这周我和伙伴对以前的四则运算项目进行了最后的修改和测试,伙伴编写了一个很棒的交互程序,同时对代码进行了格式化以及漏洞的完善,贡献很大!!
我深深地感受到Java是一门实践性很强的学问!Java的不少概念难以理解,并且就算理解了也不等于会灵活应用,因此对这门学科的学习仍是应该以实践为主!!
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 28/28 | 1/1 | 16/16 | |
第二周 | 710/738 | 1/2 | 20/36 | |
第三周 | 426/1164 | 1/3 | 16/52 | |
第四周 | 1068/2232 | 2/5 | 20/72 | |
第五周 | 604/2928 | 1/6 | 22/94 | |
第六周 | 609/3537 | 1/7 | 22/116 | |
第七周 | 599/4136 | 1/8 | 18/134 | |
第八周 | 1052/5188 | 3/11 | 20/154 | |
第九周 | 866/6054 | 1/12 | 20/174 | |
第十周 | 970/7024 | 1/13 | 20/194 |
计划学习时间:22小时
实际学习时间:20小时
改进状况:这部分学习的时候对概念的理解遇到了较大的麻烦,只能是经过不断查阅各类资料去加深本身的理解,可是有的概念总感受理解得不是那么到位!!
在查阅资料的过程当中也了解到实践的重要性,要学着把更多的精力放到实践中去,而不是一直钻概念的牛角尖!!