一、单链表的存储方式
- 头指针:指向链表第一个元素的地址值150
- data域代表此处存储的值,next域指向下一个元素的地址
- 链表是以节点的方式存储的,而且链表上相邻两个节点的地址不一定相邻,也就是说不一定是连续存放的
- 当next域为null时,表示链表结束
- 链表分为有头节点的和无头节点的链表,根据实际需求来定
二、向单链表添加元素(增)
需求:定义一组梁山好汉对象,id代表其排位。将其添加到链表中
add的思路分析:
- 找到最后一个节点,把它的next替换为要添加的元素。next为null的节点,即为最后一个节点
- 通过遍历的方式来找最后一个节点,关键在于定义辅助指针temp
public class LinkedListTest {
public static void main(String[] args){
heroNode hero1 = new heroNode(1,"宋江","及时雨");
heroNode hero2 = new heroNode(2,"卢俊义","玉麒麟");
heroNode hero3 = new heroNode(3,"吴用","智多星");
heroNode hero4 = new heroNode(4,"林冲","豹子头");
SingleLinkedList linklist1 = new SingleLinkedList();
linklist1.add(hero1);
linklist1.add(hero2);
linklist1.add(hero3);
linklist1.add(hero4);
linklist1.showLinkedList();
}
}
class heroNode{
public int id;//梁山排位
public String name;
public String nickname;
public heroNode next;//next域
public heroNode(int id, String name, String nickname){
this.id = id;
this.name = name;
this.nickname = nickname;
}
@Override
public String toString() {
return "id:"+id+" "+"name:"+name;
}
}
class SingleLinkedList{
//有头节点的链表,头节点只是通过head.next的方式,方便找到链表的第一个元素是谁
//头节点定以后一般不能改动
private heroNode head = new heroNode(0,"","");
//向链表末尾添加元素
public void add(heroNode hero){
//定义一个辅助指针
heroNode temp = head;
//遍历链表,找到最后一个元素
while (true){
if (temp.next == null){
//此时tempt就指向了最后一个元素
break;
}else {
temp = temp.next;
}
}
temp.next = hero;//添加成功
}
//显示链表所有元素
public void showLinkedList(){
heroNode temp = head;
if (head.next == null){
System.out.println("链表空");
}
while (temp.next != null){
System.out.println(temp.next);
temp = temp.next;
}
}
}
第二种添加方式
——添加时按照id顺序从小到大插入到链表
import java.util.concurrent.TimeoutException;
public class LinkedListTest {
public static void main(String[] args){
heroNode hero1 = new heroNode(1,"宋江","及时雨");
heroNode hero2 = new heroNode(2,"卢俊义","玉麒麟");
heroNode hero3 = new heroNode(3,"吴用","智多星");
heroNode hero4 = new heroNode(4,"林冲","豹子头");
SingleLinkedList linklist1 = new SingleLinkedList();
linklist1.addByOrder(hero4);
linklist1.addByOrder(hero2);
linklist1.addByOrder(hero1);
linklist1.addByOrder(hero3);
// linklist1.addByOrder(hero1);//java.lang.RuntimeException: 此好汉已经在链表中
linklist1.showLinkedList();
}
}
class heroNode{
public int id;//梁山排位
public String name;
public String nickname;
public heroNode next;//next域
public heroNode(int id, String name, String nickname){
this.id = id;
this.name = name;
this.nickname = nickname;
}
@Override
public String toString() {
return "id:"+id+" "+"name:"+name;
}
}
class SingleLinkedList{
//有头节点的链表,头节点只是通过head.next的方式,方便找到链表的第一个元素是谁
//头节点定以后一般不能改动
private heroNode head = new heroNode(0,"","");
public void addByOrder(heroNode hero){
heroNode temp = head;
/*
这个while循环是精髓,多理解几遍!
while循环的作用就是:把辅助指针temp指向的节点A,A后面插入新节点。
*/
while (true){
if (temp.next==null){//说明指针已经到链表末尾了,就插在末尾
break;
}
if (hero.id<temp.next.id){//找到位置了,插在temp的后面
break;
}
if (hero.id==temp.next.id){
throw new RuntimeException("此好汉已经在链表中");
}
temp = temp.next;
}
hero.next = temp.next;
temp.next = hero;
}
//显示链表所有元素
public void showLinkedList(){
heroNode temp = head;
if (head.next == null){
System.out.println("链表空");
}
while (temp.next != null){
System.out.println(temp.next);
temp = temp.next;
}
}
}
虽然是无序插入的,但是链表内部是按id顺序排的
三、修改链表中的某一个节点信息(改)
需求——根据新定义的一个 HeroNode newHeroNode = new HeroNode(2, "小卢", "玉麒麟~~"); ,修改链表中对应id=2的节点的name和nickname,但是不改变id。
public class LinkedListTest {
public static void main(String[] args){
heroNode hero1 = new heroNode(1,"宋江","及时雨");
heroNode hero2 = new heroNode(2,"卢俊义","玉麒麟");
heroNode hero3 = new heroNode(3,"吴用","智多星");
heroNode hero4 = new heroNode(4,"林冲","豹子头");
SingleLinkedList linklist1 = new SingleLinkedList();
linklist1.addByOrder(hero4);
linklist1.addByOrder(hero2);
linklist1.addByOrder(hero1);
linklist1.addByOrder(hero3);
// linklist1.addByOrder(hero1);//java.lang.RuntimeException: 此好汉已经在链表中
System.out.println("修改前");
linklist1.showLinkedList();
System.out.println("修改后");
linklist1.update(new heroNode(1,"小宋","大傻逼"));
linklist1.showLinkedList();
}
}
class heroNode{
public int id;//梁山排位
public String name;
public String nickname;
public heroNode next;//next域
public heroNode(int id, String name, String nickname){
this.id = id;
this.name = name;
this.nickname = nickname;
}
@Override
public String toString() {
return "id:"+id+" "+"name:"+name+" "+"nickname:"+nickname;
}
}
class SingleLinkedList{
//有头节点的链表,头节点只是通过head.next的方式,方便找到链表的第一个元素是谁
//头节点定以后一般不能改动
private heroNode head = new heroNode(0,"","");
public void addByOrder(heroNode hero){
heroNode temp = head;
/*
这个while循环是精髓,多理解几遍!
while循环的作用就是:把辅助指针temp指向的节点A,A后面插入新节点。
*/
while (true){
if (temp.next==null){//说明指针已经到链表末尾了,就插在末尾
break;
}
if (hero.id<temp.next.id){//找到位置了,插在temp的后面
break;
}
if (hero.id==temp.next.id){
throw new RuntimeException("此好汉已经在链表中");
}
temp = temp.next;
}
hero.next = temp.next;
temp.next = hero;
}
public void update(heroNode hero){
//先寻找对应id的节点
heroNode temp = head.next;
boolean flag = false;
while(true){
if (temp==null){//说明到尾部了
break;
}
if (temp.id == hero.id){
flag = true;
break;
}
temp = temp.next;
}
if (flag==true){
temp.name = hero.name;
temp.nickname = hero.nickname;
}else {
System.out.println("链表中没有此好汉!");
}
}
//显示链表所有元素
public void showLinkedList(){
heroNode temp = head;
if (head.next == null){
System.out.println("链表空");
}
while (temp.next != null){
System.out.println(temp.next);
temp = temp.next;
}
}
}
四、删除某个节点
需求——删除指定id的节点
public void delete(int ID){
heroNode temp1 = head;
heroNode temp2 = head.next;
boolean flag = false;
while (true){
if (temp2==null){
System.out.println("链表中没有此好汉");
break;
}
if (temp2.id==ID){
flag = true;//说明找到了
break;
}
temp1 = temp2;
temp2 = temp2.next;
}
if(flag){
temp1.next = temp2.next;
}
}
思路
-
定义两个辅助指针—temp1和temp2。一个指向while循环结束后,temp2指向要被删除的节点,temp1始终指向temp2的前一个节点。
-
然后将temp1和temp2.next连起来,temp2会被垃圾回收机制自动回收
-
flag的作用:让你知道while循环有没有找到对应的节点,如果找到了再进行删除,如果没找到,就不用删了
public class LinkedListTest {
public static void main(String[] args){
heroNode hero1 = new heroNode(1,"宋江","及时雨");
heroNode hero2 = new heroNode(2,"卢俊义","玉麒麟");
heroNode hero3 = new heroNode(3,"吴用","智多星");
heroNode hero4 = new heroNode(4,"林冲","豹子头");
SingleLinkedList linklist1 = new SingleLinkedList();
linklist1.addByOrder(hero4);
linklist1.addByOrder(hero2);
linklist1.addByOrder(hero1);
linklist1.addByOrder(hero3);
// linklist1.addByOrder(hero1);//java.lang.RuntimeException: 此好汉已经在链表中
System.out.println("修改前");
linklist1.showLinkedList();
System.out.println("修改后");
linklist1.update(new heroNode(1,"小宋","大傻逼"));
linklist1.showLinkedList();
linklist1.delete(1);
linklist1.delete(3);
linklist1.delete(4);
System.out.println("删除后");
linklist1.showLinkedList();
}
}
class heroNode{
public int id;//梁山排位
public String name;
public String nickname;
public heroNode next;//next域
public heroNode(int id, String name, String nickname){
this.id = id;
this.name = name;
this.nickname = nickname;
}
@Override
public String toString() {
return "id:"+id+" "+"name:"+name+" "+"nickname:"+nickname;
}
}
class SingleLinkedList{
//有头节点的链表,头节点只是通过head.next的方式,方便找到链表的第一个元素是谁
//头节点定以后一般不能改动
private heroNode head = new heroNode(0,"","");
public void addByOrder(heroNode hero){
heroNode temp = head;
/*
这个while循环是精髓,多理解几遍!
while循环的作用就是:把辅助指针temp指向的节点A,A后面插入新节点。
*/
while (true){
if (temp.next==null){//说明指针已经到链表末尾了,就插在末尾
break;
}
if (hero.id<temp.next.id){//找到位置了,插在temp的后面
break;
}
if (hero.id==temp.next.id){
throw new RuntimeException("此好汉已经在链表中");
}
temp = temp.next;
}
hero.next = temp.next;
temp.next = hero;
}
public void update(heroNode hero){
//先寻找对应id的节点
heroNode temp = head.next;
boolean flag = false;
while(true){
if (temp==null){//说明到尾部了
break;
}
if (temp.id == hero.id){
flag = true;
break;
}
temp = temp.next;
}
if (flag==true){
temp.name = hero.name;
temp.nickname = hero.nickname;
}else {
System.out.println("链表中没有此好汉!");
}
}
public void delete(int ID){
heroNode temp1 = head;
heroNode temp2 = head.next;
boolean flag = false;
while (true){
if (temp2==null){
System.out.println("链表中没有此好汉");
break;
}
if (temp2.id==ID){
flag = true;//说明找到了
break;
}
temp1 = temp2;
temp2 = temp2.next;
}
if(flag){
temp1.next = temp2.next;
}
}
//显示链表所有元素
public void showLinkedList(){
heroNode temp = head;
if (head.next == null){
System.out.println("链表空");
}
while (temp.next != null){
System.out.println(temp.next);
temp = temp.next;
}
}
}