03-数据结构与算法-链表实现
链表在内存中实际存储结构
单链表逻辑图
总结:
1、链表是以节点的方式存储,是链式存储。
2、每个节点包含data域:存储数据,next域:指向下一个节点。
3、链表各个节点不一定是连续存储。
4、链表分带头节点的链表和没有头节点的链表,根据 实际需求确定。
JAVA代码实现
//定义一个 singleLinkList 来关联英雄
class SingleLinkedList{
//先初始化一个头结点(head),头结点不能动,不存放具体数据
private HearNode head = new HearNode(0,"","");
//添加节点到单向链表
//思路,当不考虑编号的顺序的时候,
//1、找到当前链表最后节点
//2、将最后这个节点的next指向新节点
public void add(HearNode hearNode) {
//head不能动,需要一个辅助遍历temp
HearNode temp = head;
//遍历链表,找到最后
while (true) {
//当next为null,则为最后节点
if (temp.next == null){
break;
}
//未找到,就将temp后移
temp = temp.next;
}
//当退出while循坏时,则找到链表最后
temp.next = hearNode;
}
//添加有序链表
public void addByOrder(HearNode hearNode) {
//创建临时temp节点,因为头节点不能动
//因为是单链表,因此找的temp是位于添加位置的前一个节点,否则无法插入
HearNode temp = head;
boolean flag = false; //标记添加编号是否存在,默认为false,已存在,则无法添加
while (true) {
if (temp.next == null) { //说明temp在链表的最后
break;
}
if (temp.next.no > hearNode.no) { //位置找到了,就在temp的后面插入
break;
}else if (temp.next.no == hearNode.no) { //添加的数据no编号已存在
flag = true;
break;
}
//节点后移,变量当前链表
temp = temp.next;
}
//判断flag,flag为真,说明编号存在
if (flag) {
System.out.println("准备插入的节点编号"+ temp.next.no +"已存在");
}else {
//把节点插入到temp后面
hearNode.next = temp.next;
temp.next = hearNode;
}
}
//修改链表节点信息,根据no编号来修改,即no编号不能改
//根据newHearNode的no修改
public void update(HearNode newHearNode){
//判断是否为空
if (head.next == null) {
System.out.println("链表为空");
return;
}
//找到需要修改的节点,根据no编号
HearNode temp = head.next;
boolean flag = false; //表示是否找到该节点
while (true) {
if (temp == null) {
break; //链表遍历结束
}
if (temp.no == newHearNode.no) { //找到节点
flag = true;
break;
}
temp = temp.next;
}
if (flag) {
//根据flag是否找到需要修改的节点
temp.name = newHearNode.name;
temp.nickName = newHearNode.nickName;
}else {
//未找到节点
System.out.println("未找到no为" + newHearNode.no + "节点");
}
}
//删除链表节点
//1、先找到需要删除的这个节点的前一个节点temp
//2、temp.next节点指向下一个节点,即temp.next=temp.next.next
//3、被删除的节点将不会有其它引用指向,则会被垃圾回收机制回收
public void delete(int no) {
HearNode temp = head;
boolean flag = false; //标识是否找到待删除的节点的前一个节点
while (true) {
if (temp.next == null) { //已经到链表最后
break;
}
if (temp.next.no == no) {
flag = true; //找到待删除节点的前一个节点
break;
}
temp = temp.next;
}
if (flag) {
//找到待删除节点的前一个节点
temp.next = temp.next.next;
}else {
System.out.println("需要被删除的节点no:" + no + "不存在");
}
}
//显示链表
public void list() {
//先判断链表是否为空
if (head.next == null) {
System.out.println("链表为空");
return;
}
//因为头节点不能动,因此我们需要一个临时temp来遍历
HearNode temp = head.next;
while (true) {
//判断是否到链表最后
if (temp == null) {
break;
}
//输出节点信息
System.out.println(temp);
//将next后移
temp = temp.next;
}
}
}
//定义一个hearNode,每个hearNode对象就是一个节点
class HearNode{
public int no;
public String name;
public String nickName;
public HearNode next; //下一个节点
public HearNode(int no,String name,String nickName) {
this.no = no;
this.name = name;
this.nickName = nickName;
}
@Override
public String toString() {
return "HearNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickName='" + nickName + '\'' +
'}';
}
}
测试代码
public class SingleLinkListDemo {
public static void main(String[] args) {
HearNode hearNode1 = new HearNode(1,"松江","及时雨");
HearNode hearNode2 = new HearNode(2,"卢俊义","玉麒麟");
HearNode hearNode3 = new HearNode(3,"吴勇","智多星");
HearNode hearNode4 = new HearNode(4,"林冲","豹子头");
//创建链表
SingleLinkedList singleLinkedList = new SingleLinkedList();
singleLinkedList.addByOrder(hearNode3);
singleLinkedList.addByOrder(hearNode1);
singleLinkedList.addByOrder(hearNode4);
singleLinkedList.addByOrder(hearNode2);
//打印显示
singleLinkedList.list();
//测试修改节点
HearNode newHearNode = new HearNode(2,"小卢","玉麒麟");
singleLinkedList.update(newHearNode);
System.out.println("修改后的链表:");
//打印显示
singleLinkedList.list();
//测试删除节点
singleLinkedList.delete(1);
System.out.println("删除后节点:");
singleLinkedList.list();
}
}