单链表代码实现和讲解
2019-09-19 14:29
1871 查看
1、链表的特性
链表分为单链表和多链表,链表相对于数组有什么好处?
- 不是按顺序存储,是链式存储,以节点的形式
-
每个节点都包含date域(节点的内容),next域(下一节点的位置)
- 链表可以没有头节点
- 链表按照节点的next来查找下一个节点,由此当查找时,必须从头开始找,查找麻烦;但是插入和删除时只需要改变前后节点的指定位置就可以,所以插入删除方便
2、代码讲解单链表的应用(代码实现)
//实体类 public class PersonNode { public int no; public String name; public PersonNode next; public PersonNode(int no, String name) { this.no = no; this.name = name; } @Override public String toString() { return "PersonNode{" + "no=" + no + ", name='" + name + '\'' + '}'; } }
-
添加节点
//添加操作 public void add(PersonNode personNode){ //head节点不能动,需要一个节点进行辅助遍历 PersonNode temp=head; while (true){ if (temp.next==null){ //遍历链表到结尾,跳出循环执行添加操作 break; } temp=temp.next; //辅助节点后移 } temp.next=personNode;//将当前节点添加到最后一位 }
我们测试时发现如果不按顺序添加,如下图,我添加顺序时1423,输出也是按照添加顺序输出,可不可以实现按照大小顺序输出呢?
-
顺序添加
我们只需要在添加的遍历过程中加入判断条件,遍历过程中如果当前节点比下一个节点数值小,就添加在它的前面
pnode.next=temp.next;//当前节点的next指向下一个节点的next,如图,数据2的next指向数据4的next,就插入到数据4的前面 temp.next=pnode;//插入后需要让temp的next指向自己,才能实现添加
//顺序添加 public void addBySort(PersonNode pnode){ //先顶一个指示 PersonNode temp=head; boolean flag=false;//设置一个判断条件,如果遍历过程中发现该no已经存在,就置为true并跳出循环 while (true){ if (temp.next==null){ //System.out.println("add遍历已经结束"); break; } if (pnode.no<temp.next.no){ break; } else if (pnode.no==temp.next.no){ flag=true; break; } temp=temp.next; } if (flag){ System.out.println("节点已经存在"); //当flag为true时该节点已经存在 }else { pnode.next=temp.next; temp.next=pnode; } }
-
修改
修改和顺序添加类似,就是在遍历过程中找到指定的no进行修改,没有找到就跳出循环
//修改 public void UpdateNode(PersonNode personNode){ if (head.next==null){ System.out.println("别修改了,这是空链表"); return; } PersonNode temp=head.next; boolean flag=false; while (true){ if (temp==null){ break; } if (temp.no==personNode.no){ flag=true; break; } temp=temp.next; } if (flag){ temp.no=personNode.no; temp.name=personNode.name; }else{ System.out.println("没找到,不改了"); } }
-
获取链表列表的内容
< 105a span style="color: #008000;">//列表 public void list(){ if (head.next==null){ System.out.println("还找列表?这是个空的"); return; } PersonNode temp=head.next; while (true){ if (temp==null){ System.out.println("好的您已经遍历完了"); break; } System.out.println(temp); temp=temp.next; } }
-
删除操作
最重要的一句就是遍历过程中的 temp.next=temp.next.next,意思是将当前节点的next直接跳过下一个节点,指向下下个节点,而被删除的节点就相当于野指针,被内存回收
还需要注意temp这里指向的是head不是head.next,就是找到这个需要删除的节点时,temp在这个删除节点之前,为什么这样做?因为单链表和双链表不一样,双链表可以自我删除,单链表不行,必须借助前面的节点进行删除,和双链表记得区分开
//删除 public void removeNode(int num){ PersonNode temp=head; boolean flag=false; while (true){ if (temp.next==null){//遍历结束 break; } if (temp.next.no==num){ flag=true; break; } temp=temp.next; } if (flag){ temp.next=temp.next.next; }else{ System.out.println("抱歉,没有找到"); }
-
单链表反转(扩展)
/** * 链表反转(头摘法) * 思路:定义一个新的表头,把原来表的节点逐个取出,每次都放在新头节点的后面 * cur当前节点,next当前节点的下一个节点,reverseHead新的头节点 */ public void reverseList(PersonNode head){ if (head.next==null || head.next.next==null){ return; } PersonNode cur=head.next; PersonNode next=null; PersonNode reverseHead=new PersonNode(0,""); while (cur!=null){ next=cur.next; cur.next=reverseHead.next;//让当前摘下的节点指向新链表头节点后面节点的前面,相当于插队到新的头节点的后面 reverseHead.next=cur;//让头节点指向当前节点 cur=next;//指针后移 } head.next=reverseHead.next;//将原来的头节点指向新的头节点 }
-
链表逆向输出(不能用上面的头插法,因为会破坏链表结构,这个时候可以用栈的先入后出)
/** * 链表反向输出打印(不能用头摘法,会破坏链表结构),栈先进后出可实现 */ public void reversePrint(PersonNode head){ if (head.next==null || head.next.next==null){ return; } Stack<PersonNode> stackAdd=new Stack<>(); PersonNode cur=head.next; while (cur!=null){ stackAdd.push(cur); cur=cur.next; } //输出打印 while (stackAdd.size()>0){ System.out.println(stackAdd.pop()); } }
相关文章推荐
- Python单链表简单实现代码
- java 编写代码实现Stack类 ,采用单链表
- UDP内网穿透讲解及代码实现
- 单链表的链式表示和实现(含代码)
- 算法与数据结构-字符串 讲解与java代码实现
- UDP内网穿透讲解及代码实现
- 算法与数据结构-动态规划 讲解与java代码实现
- 单链表的C++代码实现
- 实例讲解PHP中实现代码重用的两个函数
- javaee实战项目--农贸产品开发(详细讲解及代码实现)
- PHP单链表的实现代码
- ios代码实现Autolayout(自动布局)的简单讲解
- [置顶] 题目:代码实现判断单链表是否有环
- 第54课: 作业讲解与广告点击实现代码
- Android插件化完美实现代码资源加载及原理讲解 附可运行demo
- JS让图片无缝滚动的实现(JS代码讲解,非直拷型内容)
- php单链表实现代码分享
- 算法与数据结构-二叉树 讲解与java代码实现
- 讲解如何让 ASP.NET 实现获取xxxxxx rank值的代码数据
- 模块度(Modularity)与Fast Newman算法讲解与代码实现