1、源码
Player实体类
package com.study.linkedlist;public class Player {public int no;public String name;public Player next;public Player(int no, String name) {this.no = no;this.name = name;}public Player() {}@Overridepublic String toString() {return "Player{" +"no=" + no +", name='" + name + '\'' +'}';}}
SingleLinkedList类
package com.study.linkedlist;import java.util.HashSet;import java.util.Stack;public class SingleLinkedList {//初始化头结点private Player p = new Player(0,"");public Player getP() {return p;}//添加节点到链表中//不考虑编号顺序//1.找到当前链表的最后一个节点//2.将最后节点的next指向新的节点public void add(Player player){//定义一个零时的头结点Player temp = p;//遍历链表,找到最后一个节点while (true){if(temp.next == null){break;}temp = temp.next;}temp.next=player;}//添加方法二:按顺序添加,并且添加编号相同的数据时提示添加错误public void addByNo(Player player){//定义一个零时的头结点Player temp = p;boolean flag = false;//定义一个标识,判断链表中是否已经存在相同的编号while (true){if (temp.next==null){break;}if (temp.next.no > player.no){break;}else if (temp.next.no == player.no){flag = true;//说明编号存在;break;}temp = temp.next;}if (flag){System.out.println("球员已经存在,不能加入"+temp.next.no+temp.next.name);}else {player.next = temp.next;temp.next = player;}}//根据编号修改球员信息public void updateByNo(Player player){//判断链表是否为空if (p.next==null){System.out.println("链表为空");return;}Player temp = p.next;boolean flag = false;while (true){if(temp.next==null){break;}if(temp.no==player.no){flag = true;break;}temp = temp.next;}if(flag){temp.name= player.name;}else {System.out.println("没有找到改球员");}}//根据编号删除节点public void deleteByNo(int no){//判断链表是否为空if (p.next==null){System.out.println("链表为空");return;}Player temp = p.next;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("没有找到改球员");}}//获取链节点的有效个数public int getLength(Player p){if (p.next==null){System.out.println("链表为空");return 0;}int length = 0;Player temp = p.next;while (temp!=null){length++;temp = temp.next;}return length;}//查找单链表中倒数第k个节点public void getByNo(Player p,int no){if (p.next==null){System.out.println("链表为空");return;}int l = getLength(p);if (no<0 || no >l){System.out.println("没有该节点");return;}Player temp = p.next;for (int i = 0; i < l - no; i++) {temp = temp.next;}System.out.println("倒数第"+no+"个节点的数据为:"+temp.no+temp.name);}//翻转链表public void reverse(Player p){if (p.next==null || p.next.next==null){System.out.println("链表为空");return;}Player reversePlayer = new Player(0,"");Player temp = p.next;Player next = null;while (temp != null){next = temp.next;temp.next = reversePlayer.next;reversePlayer.next =temp;temp = next;}p.next = reversePlayer. next;}//从尾到头打印链表public void reversePrint(Player p){if (p.next==null || p.next.next==null){System.out.println("链表为空");return;}Player temp = p.next;Stack<Player> stack = new Stack<>();while (temp != null){stack.push(temp);temp = temp.next;}while (stack.size()>0){System.out.println(stack.pop());}}//方法一:合并两个有序的单链表(缺陷:使用的addByNo方法,所以相同编号的节点会被删掉一个)public SingleLinkedList merge(SingleLinkedList sll1,SingleLinkedList sll2){//判断链表是否为空if (sll1==null){System.out.println(sll2);return null;}if (sll2==null){System.out.println(sll1);return null;}if (sll1==null&&sll2==null){System.out.println("两个链表都为空");return null;}//获取sll2的头结点Player p = sll2.getP();Player temp =p.next;//定义一个集合,用来存取遍历出来sll2的节点HashSet<Player> set = new HashSet<>();//获取sll2的节点的个数int length = sll2.getLength(p);//遍历sll2链表,并将其存到集合中for (int i = 0; i < length; i++) {set.add(temp);temp =temp.next;}//遍历集合,将其添加的sll1中for (Player player : set) {sll1.addByNo(player);}return sll1;}//方法二:合并两个有序的单链表(遍历两个链表的每个节点,判断节点编号的大小,进行排序,最后将剩余一个不是空的链表插入到最后面)public SingleLinkedList merge2(SingleLinkedList sll1,SingleLinkedList sll2){//创建一个新链表SingleLinkedList sll3 = new SingleLinkedList();Player p = sll3.getP();//获取新链表的头结点Player temp = p;//定义一个辅助头结点//获sll1的头结点Player p1 = sll1.getP();Player temp1 = p1.next;//获sll2的头结点Player p2 = sll2.getP();Player temp2 = p2.next;while (temp1!=null&&temp2!=null){if(temp1.no>temp2.no){temp.next=temp2;temp2 = temp2.next;}else {temp.next=temp1;temp1 = temp1.next;}temp = temp.next;}temp.next = temp1!=null?temp1:temp2;return sll3;}//显示整个链表public void show(){//判断链表是否为空if(p.next==null){System.out.println("链表为空");return;}//定义一个辅助头结点Player temp = p.next;//遍历链表while (temp!=null){System.out.println(temp);temp = temp.next;}}}
SingleLinkedListDemo测试类
package com.study.linkedlist;
public class SingleLinkedListDemo {
public static void main(String[] args) {
SingleLinkedList singleLinkedList = new SingleLinkedList();
singleLinkedList.addByNo(new Player(11,"欧文"));
singleLinkedList.addByNo(new Player(23,"詹姆斯"));
singleLinkedList.addByNo(new Player(34,"安特托昆博"));
singleLinkedList.addByNo(new Player(30,"库里"));
singleLinkedList.addByNo(new Player(24,"科比"));
int l = singleLinkedList.getLength(singleLinkedList.getP());
System.out.println("有效的头结点个数为:"+l);
singleLinkedList.reversePrint(singleLinkedList.getP());
singleLinkedList.reverse(singleLinkedList.getP());
singleLinkedList.getByNo(singleLinkedList.getP(),6);
singleLinkedList.show();
}
}
部分方法测试结果

2、总结
2.1、增加一个节点(增加到链表的最后)
//添加节点到链表中
//不考虑编号顺序
//1.找到当前链表的最后一个节点
//2.将最后节点的next指向新的节点
public void add(Player player){
//定义一个零时的头结点
Player temp = p;
//遍历链表,找到最后一个节点
while (true){
if(temp.next == null){
break;
}
temp = temp.next;
}
temp.next=player;
}
2.2、按顺序增加一个节点
//添加方法二:按顺序添加,并且添加编号相同的数据时提示添加错误
public void addByNo(Player player){
//定义一个零时的头结点
Player temp = p;
boolean flag = false;//定义一个标识,判断链表中是否已经存在相同的编号
while (true){
if (temp.next==null){
break;
}
if (temp.next.no > player.no){
break;
}else if (temp.next.no == player.no){
flag = true;//说明编号存在;
break;
}
temp = temp.next;
}
if (flag){
System.out.println("球员已经存在,不能加入"+temp.next.no+temp.next.name);
}else {
player.next = temp.next;
temp.next = player;
}
}
2.3、修改一个节点
//根据编号修改球员信息
public void updateByNo(Player player){
//判断链表是否为空
if (p.next==null){
System.out.println("链表为空");
return;
}
Player temp = p.next;
boolean flag = false;
while (true){
if(temp.next==null){
break;
}
if(temp.no==player.no){
flag = true;
break;
}
temp = temp.next;
}
if(flag){
temp.name= player.name;
}else {
System.out.println("没有找到改球员");
}
}
2.4、删除一个节点
//根据编号删除节点
public void deleteByNo(int no){
//判断链表是否为空
if (p.next==null){
System.out.println("链表为空");
return;
}
Player temp = p.next;
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("没有找到改球员");
}
}
2.5、获取节点有效个数
//获取链节点的有效个数
public int getLength(Player p){
if (p.next==null){
System.out.println("链表为空");
return 0;
}
int length = 0;
Player temp = p.next;
while (temp!=null){
length++;
temp = temp.next;
}
return length;
}
2.6、查找链表中倒数第K个节点(重点,leetcode原题)
在已知链表的长度下:
//查找单链表中倒数第k个节点
public void getByNo(Player p,int no){
if (p.next==null){
System.out.println("链表为空");
return;
}
int l = getLength(p);
if (no<0 || no >l){
System.out.println("没有该节点");
return;
}
Player temp = p.next;
for (int i = 0; i < l - no; i++) {
temp = temp.next;
}
System.out.println("倒数第"+no+"个节点的数据为:"+temp.no+temp.name);
}
链表的长度未知,可采用双指针来查找:
//核心代码
ListNode first = head,last = head;
for(int i=0;i<k;i++){
if(first==null){
return null;
}
first = first.next;
}
while(first!=null){
first = first.next;
last = last.next;
}
return last;
2.7、翻转链表(重点,LeetCode原题)
//翻转链表
public void reverse(Player p){
if (p.next==null || p.next.next==null){
System.out.println("链表为空");
return;
}
Player reversePlayer = new Player(0,"");
Player temp = p.next;
Player next = null;
while (temp != null){
next = temp.next;
temp.next = reversePlayer.next;
reversePlayer.next =temp;
temp = next;
}
p.next = reversePlayer. next;
}
2.8、从尾到头打印链表(重点,LeetCode原题)
//从尾到头打印链表
//采用栈的特点
public void reversePrint(Player p){
if (p.next==null || p.next.next==null){
System.out.println("链表为空");
return;
}
Player temp = p.next;
Stack<Player> stack = new Stack<>();
while (temp != null){
stack.push(temp);
temp = temp.next;
}
while (stack.size()>0){
System.out.println(stack.pop());
}
}
2.9、合并两个有序的链表(重点,leetcode原题)
public SingleLinkedList merge2(SingleLinkedList sll1,SingleLinkedList sll2){
//创建一个新链表
SingleLinkedList sll3 = new SingleLinkedList();
Player p = sll3.getP();//获取新链表的头结点
Player temp = p;//定义一个辅助头结点
//获sll1的头结点
Player p1 = sll1.getP();
Player temp1 = p1.next;
//获sll2的头结点
Player p2 = sll2.getP();
Player temp2 = p2.next;
while (temp1!=null&&temp2!=null){
if(temp1.no>temp2.no){
temp.next=temp2;
temp2 = temp2.next;
}else {
temp.next=temp1;
temp1 = temp1.next;
}
temp = temp.next;
}
temp.next = temp1!=null?temp1:temp2;
return sll3;
}
