单链表内存结构
单链表的逻辑结构
单向链表
单向链表定义
1、链表是以节点方式储存,是链式储存
2、每个节点包含data域,next域(指向下一个节点)
3、链表的各个节点不一定是连续储存
4、链表分为带头节点的链表和不带头节点的链表
5、链表的内存结构
单向链表应用
使用链表对池塘鱼儿的增删改查
1、增
/**
* 思路:
* 1、找到当前链表的最后节点
* 2、将最后这个节点的next指向新的节点
*/
public void add(girlfriendsNode gfNode) {
//因为头节点(head)不能动,因此我们需要一个辅助
girlfriendsNode temp = head;
//遍历链表,找到最后
while (true) {
//找到链表的最后
if (temp.next == null) {
break;
}
//如果没有找到最后,将temp后移
temp = temp.next;
}
//当退出循环时,temp就指向了链表的最后
temp.next = gfNode;
}
2、删
/**
* 思路
* 1、head头节点不能动,因此我们需要一个temp辅助节点找到待删除的前一个节点
* 2、说明我们在比较时,是temp.next.no和需要删除的节点的no比较
*/
public void delete(int no) {
girlfriendsNode temp = head;
//是否找到节点
boolean flag = false;
//判空
while (true) {
if (temp.next == null) {
//已经找到链表最后
break;
}
if (temp.no == no) {
//找到的待删除节点的前一个节点temp
flag = true;
break;
}
temp = temp.next;//后移
}
//判断flag
if (flag) {
//找到
//删除
temp.next = temp.next.next;//相当于下一个节点下标赋给前一个节点下标
} else {
System.out.printf("无法删除%d号节点",no);
}
}
3、改
//修改节点信息,根据no编号来修改,跟数据库的修改操作是一个意思
public void update(girlfriendsNode newgirlfriendsNode) {
//判空
if (head.next == null) {
System.out.println("链表为空");
return;
}
//定义辅助节点,找到需要修改的节点,根据no编号
girlfriendsNode temp = head;
Boolean flag = false;//表示是否找到该节点,没找到就不能修改
while (true) {
if (temp == null) {
break;//说明此时指针在链表最后
}
if (temp.no == newgirlfriendsNode.no) {
//找到节点
flag = true;
break;
}
temp = temp.next;
}
//根据flag,判断是否找到要修改的节点
if (flag) {
temp.name = newgirlfriendsNode.name;
temp.nickname = newgirlfriendsNode.nickname;
} else {
//没找到节点
System.out.printf("没有找到编号%d的节点", newgirlfriendsNode.no);
}
}
4、查
//显示链表
public void list() {
//判断链表是否为空
if (head.next == null) {
System.out.println("链表为空");
return;
}
//因为头节点不能动,需要用上面的辅助节点来遍历
girlfriendsNode temp = head.next;
while (true) {
//判断是否到了链表的最后
if (temp == null) {
break;
}
//输出节点信息
System.out.println(temp);
//将节点后移
temp = temp.next;
}
}
完整代码
package linkedlist;
/**
* @author shkstart
* @create 2021-07-27 14:34
*/
public class SingleLinkListDemo {
public static void main(String[] args) {
//测试
//创建节点
girlfriendsNode gf1 = new girlfriendsNode(1, "莺莺", "肤白");
girlfriendsNode gf2 = new girlfriendsNode(2, "燕燕", "貌美");
girlfriendsNode gf3 = new girlfriendsNode(3, "红红", "大长腿");
girlfriendsNode gf4 = new girlfriendsNode(4, "绿绿", "傻白甜");
//创建链表
SingleLinkedlist singleLinkedlist = new SingleLinkedlist();
//把节点加入链表
singleLinkedlist.add(gf1);
singleLinkedlist.add(gf2);
singleLinkedlist.add(gf3);
singleLinkedlist.add(gf4);
//显示链表
System.out.println("修改前");
singleLinkedlist.list();
//测试修改节点的代码
girlfriendsNode newgf = new girlfriendsNode(3, "豆豆", "大长腿");
System.out.println("修改后");
singleLinkedlist.update(newgf);
singleLinkedlist.list();
//删除一个节点的方法
System.out.println("删除节点之后");
singleLinkedlist.delete(3);
singleLinkedlist.list();
}
}
//定义链表,管理备胎
class SingleLinkedlist {
//初始化头节点
private girlfriendsNode head = new girlfriendsNode(0, "", "");
//添加节点到链表
/**
* 思路:
* 1、找到当前链表的最后节点
* 2、将最后这个节点的next指向新的节点
*/
public void add(girlfriendsNode gfNode) {
//因为头节点(head)不能动,因此我们需要一个辅助
girlfriendsNode temp = head;
//遍历链表,找到最后
while (true) {
//找到链表的最后
if (temp.next == null) {
break;
}
//如果没有找到最后,将temp后移
temp = temp.next;
}
//当退出循环时,temp就指向了链表的最后
temp.next = gfNode;
}
//修改节点信息,根据no编号来修改,跟数据库的修改操作是一个意思
public void update(girlfriendsNode newgirlfriendsNode) {
//判空
if (head.next == null) {
System.out.println("链表为空");
return;
}
//定义辅助节点,找到需要修改的节点,根据no编号
girlfriendsNode temp = head;
Boolean flag = false;//表示是否找到该节点,没找到就不能修改
while (true) {
if (temp == null) {
break;//说明此时指针在链表最后
}
if (temp.no == newgirlfriendsNode.no) {
//找到节点
flag = true;
break;
}
temp = temp.next;
}
//根据flag,判断是否找到要修改的节点
if (flag) {
temp.name = newgirlfriendsNode.name;
temp.nickname = newgirlfriendsNode.nickname;
} else {
//没找到节点
System.out.printf("没有找到编号%d的节点", newgirlfriendsNode.no);
}
}
//删除节点
/**
* 思路
* 1、head头节点不能动,因此我们需要一个temp辅助节点找到待删除的前一个节点
* 2、说明我们在比较时,是temp.next.no和需要删除的节点的no比较
*/
public void delete(int no) {
girlfriendsNode temp = head;
//是否找到节点
boolean flag = false;
//判空
while (true) {
if (temp.next == null) {
//已经找到链表最后
break;
}
if (temp.no == no) {
//找到的待删除节点的前一个节点temp
flag = true;
break;
}
temp = temp.next;//后移
}
//判断flag
if (flag) {
//找到
//删除
temp.next = temp.next.next;//相当于下一个节点下标赋给前一个节点下标
} else {
System.out.printf("无法删除%d号节点",no);
}
}
//显示链表
public void list() {
//判断链表是否为空
if (head.next == null) {
System.out.println("链表为空");
return;
}
//因为头节点不能动,需要用上面的辅助节点来遍历
girlfriendsNode temp = head.next;
while (true) {
//判断是否到了链表的最后
if (temp == null) {
break;
}
//输出节点信息
System.out.println(temp);
//将节点后移
temp = temp.next;
}
}
}
//定义girlfriendsNode节点,每一个girlfriendsNode 对象被称为一个节点
class girlfriendsNode {
public int no;//备胎编号
public String name;//备胎名字
public String nickname;//备胎昵称
public girlfriendsNode next;//指向下一个节点
//构造器
public girlfriendsNode(int no, String name, String nickname) {
this.no = no;
this.name = name;
this.nickname = nickname;
}
//重写tostring
@Override
public String toString() {
return "girlfriendsNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}
双向链表
双向链表定义
双向链表也叫双链表,它的每个数据节点中都有两个指针这里与单向链表是不同的,分别指向直接后继和直接前驱。(形成一个完整闭环)所以,从双向链表中的任意一个节点开始,都可以很方便地访问它的前节点和后节点
双向链表逻辑结构
双向链表应用
1、增
public void add(girlfriendsNode1 gfNode) {
//因为头节点(head)不能动,因此我们需要一个辅助
girlfriendsNode1 temp = head;
//遍历链表,找到最后
while (true) {
//找到链表的最后
if (temp.next == null) {
break;
}
//如果没有找到最后,将temp后移
temp = temp.next;
}
//当退出循环时,temp就指向了链表的最后
temp.next=gfNode;
gfNode.piror=temp;
}
2、删
public void delete(int no) {
//判断当前链表是否为空
if(head.next==null){
//空链表
System.out.println("空链表,不能删除");
return;
}
girlfriendsNode1 temp = head.next;
//是否找到节点
boolean flag = false;
//判空
while (true) {
if (temp == null) {
//已经找到链表最后
break;
}
if (temp.no == no) {
//找到的待删除节点的前一个节点temp
flag = true;
break;
}
temp = temp.next;//后移
}
//判断flag
if (flag) {
//找到
//删除
//temp.next = temp.next.next;//单向链表的删除方式
temp.piror.next=temp.next;
//如果最后一个节点不为空
if(temp.next!=null){
temp.next.piror=temp.piror;
}
} else {
System.out.printf("无法删除%d号节点",no);
}
}
3、改
public void update(girlfriendsNode1 newgirlfriendsNode) {
//判空
if (head.next == null) {
System.out.println("链表为空");
return;
}
//定义辅助节点,找到需要修改的节点,根据no编号
girlfriendsNode1 temp = head;
Boolean flag = false;//表示是否找到该节点,没找到就不能修改
while (true) {
if (temp == null) {
break;//说明此时指针在链表最后
}
if (temp.no == newgirlfriendsNode.no) {
//找到节点
flag = true;
break;
}
temp = temp.next;
}
//根据flag,判断是否找到要修改的节点
if (flag) {
temp.name = newgirlfriendsNode.name;
temp.nickname = newgirlfriendsNode.nickname;
} else {
//没找到节点
System.out.printf("没有找到编号%d的节点", newgirlfriendsNode.no);
}
}
4、查
public void list() {
//判断链表是否为空
if (head.next == null) {
System.out.println("链表为空");
return;
}
//因为头节点不能动,需要用上面的辅助节点来遍历
girlfriendsNode1 temp = head.next;
while (true) {
//判断是否到了链表的最后
if (temp == null) {
break;
}
//输出节点信息
System.out.println(temp);
//将节点后移
temp = temp.next;
}
}
完整代码
package linkedlist;
/**
* 双链表
* @author shkstart
* @create 2021-07-28 13:03
*/
public class DoubleLinkedListDemo {
public static void main(String[] args) {
//创建节点
girlfriendsNode1 gf1 = new girlfriendsNode1(1, "莺莺", "肤白");
girlfriendsNode1 gf2 = new girlfriendsNode1(2, "燕燕", "貌美");
girlfriendsNode1 gf3 = new girlfriendsNode1(3, "红红", "大长腿");
girlfriendsNode1 gf4 = new girlfriendsNode1(4, "绿绿", "傻白甜");
//创建一个双向链表对象
DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
doubleLinkedList.add(gf1);
doubleLinkedList.add(gf2);
doubleLinkedList.add(gf3);
doubleLinkedList.add(gf4);
System.out.println("双向链表");
doubleLinkedList.list();
//修改
System.out.println("修改节点后的双向链表");
girlfriendsNode1 newgf1 = new girlfriendsNode1(3, "小不点", "长发飘飘");
doubleLinkedList.update(newgf1);
doubleLinkedList.list();
//删除节点
System.out.println("删除一个指定节点后");
doubleLinkedList.delete(1);
doubleLinkedList.list();
}
}
//创建一个双链表类
class DoubleLinkedList{
//先初始化一个头节点,头节点不动,不存放数据
private girlfriendsNode1 head=new girlfriendsNode1(0,"","");
//返回头节点
public girlfriendsNode1 getHead(){
return head;
}
//查看双链表(遍历)
public void list() {
//判断链表是否为空
if (head.next == null) {
System.out.println("链表为空");
return;
}
//因为头节点不能动,需要用上面的辅助节点来遍历
girlfriendsNode1 temp = head.next;
while (true) {
//判断是否到了链表的最后
if (temp == null) {
break;
}
//输出节点信息
System.out.println(temp);
//将节点后移
temp = temp.next;
}
}
//添加节点到双向链表最后
public void add(girlfriendsNode1 gfNode) {
//因为头节点(head)不能动,因此我们需要一个辅助
girlfriendsNode1 temp = head;
//遍历链表,找到最后
while (true) {
//找到链表的最后
if (temp.next == null) {
break;
}
//如果没有找到最后,将temp后移
temp = temp.next;
}
//当退出循环时,temp就指向了链表的最后
temp.next=gfNode;
gfNode.piror=temp;
}
//修改一个节点的内容
public void update(girlfriendsNode1 newgirlfriendsNode) {
//判空
if (head.next == null) {
System.out.println("链表为空");
return;
}
//定义辅助节点,找到需要修改的节点,根据no编号
girlfriendsNode1 temp = head;
Boolean flag = false;//表示是否找到该节点,没找到就不能修改
while (true) {
if (temp == null) {
break;//说明此时指针在链表最后
}
if (temp.no == newgirlfriendsNode.no) {
//找到节点
flag = true;
break;
}
temp = temp.next;
}
//根据flag,判断是否找到要修改的节点
if (flag) {
temp.name = newgirlfriendsNode.name;
temp.nickname = newgirlfriendsNode.nickname;
} else {
//没找到节点
System.out.printf("没有找到编号%d的节点", newgirlfriendsNode.no);
}
}
//从双链表中删除一个节点
//直接找到要删除的节点
//找到之后直接删除
public void delete(int no) {
//判断当前链表是否为空
if(head.next==null){
//空链表
System.out.println("空链表,不能删除");
return;
}
girlfriendsNode1 temp = head.next;
//是否找到节点
boolean flag = false;
//判空
while (true) {
if (temp == null) {
//已经找到链表最后
break;
}
if (temp.no == no) {
//找到的待删除节点的前一个节点temp
flag = true;
break;
}
temp = temp.next;//后移
}
//判断flag
if (flag) {
//找到
//删除
//temp.next = temp.next.next;//单向链表的删除方式
temp.piror.next=temp.next;
//如果最后一个节点不为空
if(temp.next!=null){
temp.next.piror=temp.piror;
}
} else {
System.out.printf("无法删除%d号节点",no);
}
}
}
//定义girlfriendsNode1,每个girlfriendsNode1对象就是一个节点
class girlfriendsNode1 {
public int no;//备胎编号
public String name;//备胎名字
public String nickname;//备胎昵称
public girlfriendsNode1 next;//指向下一个节点
public girlfriendsNode1 piror;//指向前一个节点
//构造器
public girlfriendsNode1(int no, String name, String nickname) {
this.no = no;
this.name = name;
this.nickname = nickname;
}
//重写tostring
@Override
public String toString() {
return "girlfriendsNode1{" +
"no=" + no +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}