java实现单链表及其反转
提示:以下是本篇文章正文内容,下面案例可供参考
一、单链表是什么?
单链表是一种链式存取的数据结构,其中每个元素视为一个结点,一个结点包含dataNode(数据域,存放实际数据)以及nextNode(指针域,指向下一级结点),其中头结点的dataNode为空,nextNode连接新结点。
二、java实现单链表
1.创建SingleLinkList类
代码如下(示例):
import java.util.Comparator;
/**
* @author: pikachu
* @description: 单链表
*/
public class SingleLinkList<E> {
//初始化头结点
private final MyNode<E> headNode = new MyNode<E>(null, null);
public MyNode<E> getHeadNode() {
return headNode;
}
//静态内部类,表示节点类,dataNode为可为自定义类
private static class MyNode<E> {
//数据域
private E dataNode;
//指针域
private MyNode nextNode;
public MyNode(E dataNode, MyNode nextNode) {
this.dataNode = dataNode;
this.nextNode = nextNode;
}
}
//添加到尾部
public void addToRear(E dataNode) {
MyNode temp = headNode;
while (temp.nextNode != null) {
temp = temp.nextNode;
}
temp.nextNode = new MyNode(dataNode, null);
}
//添加到头部
public void addToHead(E dataNode){
MyNode temp = headNode.nextNode;
headNode.nextNode = new MyNode(dataNode, temp);
}
//按照dataNode特定属性(从小到大)插入入链表,比较器用于对该属性进行比较大小
public void addByAttr(E dataNode, Comparator<E> comparator) {
MyNode temp = headNode;
while (temp.nextNode != null) {
//找到单链表中第一个数据域大于需要插入的节点的数据域dataNode,temp指向插入位置的前一个节点
if (comparator.compare((E) temp.nextNode.dataNode, dataNode) > 0) {
break;
}
temp = temp.nextNode;
}
temp.nextNode = new MyNode(dataNode, temp.nextNode);
}
//更新newNode中特定属性与链表中有相同节点的信息
public boolean updateNode(E newDataNode, Comparator<E> comparator) {
MyNode temp = headNode;
while (temp.nextNode != null) {
if (comparator.compare((E) temp.nextNode.dataNode, newDataNode) == 0) {
MyNode newNode = new MyNode(newDataNode, temp.nextNode.nextNode);
temp.nextNode = newNode;
return true;
}
temp = temp.nextNode;
}
return false;
}
//删除特定节点
public boolean deleteNode(E delNode, Comparator<E> comparator) {
MyNode temp = headNode;
boolean flag = false;
while (temp.nextNode != null) {
if (comparator.compare((E) temp.nextNode.dataNode, delNode) == 0) {
temp.nextNode = temp.nextNode.nextNode;
flag = true;
}
temp = temp.nextNode;
}
return flag;
}
//打印链表
public void printLinkList() {
MyNode temp = headNode;
if (headNode.nextNode == null) {
System.out.println("LinkList is empty!");
return;
}
while (temp.nextNode != null) {
temp = temp.nextNode;
System.out.println(temp.dataNode);
}
}
//获取有效节点数
public static int getValidDataNums(MyNode headNode) {
int i = 0;
MyNode temp = headNode;
while (temp.nextNode != null) {
i++;
temp = temp.nextNode;
}
return i;
}
//查找单链表中倒数第k个节点
public E getInverseKNode(MyNode headNode,int index){
MyNode<E> temp = headNode;
int nums = getValidDataNums(headNode);
if (index> nums||index<=0) {
return null;
}
for (int i = 0; i < nums -index+1; i++) {
temp = temp.nextNode;
}
return temp.dataNode;
}
//反转单链表
public static void inverseLinkList(MyNode headNode){
MyNode q = headNode.nextNode;
MyNode p = q.nextNode;
MyNode t = p;
//有效节点数<=1
if (q == null||p==null) {
return;
}
else {
//临时保存第一个节点,不能在反转前将最后一个节点的nextNode置空
MyNode lastNode = q;
while (t.nextNode != null) {
t = t.nextNode;
p.nextNode = q;
q = p;
p = t;
}
//t移动到最后一个节点时,p也指向最后一个节点
headNode.nextNode = p;
p.nextNode = q;
lastNode.nextNode = null;
}
}
}
class Hero {
private int no;
private String name;
public Hero(int no, String name) {
this.no = no;
this.name = name;
}
public int getNo() {
return no;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Hero{" +
"no=" + no +
", name='" + name + '\'' +
'}';
}
}
2.编写测试类
代码如下:
class Hero {
private int no;
private String name;
public Hero(int no, String name) {
this.no = no;
this.name = name;
}
public int getNo() {
return no;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Hero{" +
"no=" + no +
", name='" + name + '\'' +
'}';
}
}
class Test3 {
public static void main(String[] args) {
Comparator<Hero> heroComparator = Comparator.comparing(Hero::getNo);
SingleLinkList<Hero> singleLinkList = new SingleLinkList<>();
System.out.println("getValidDataNums() = " + SingleLinkList.getValidDataNums(singleLinkList.getHeadNode()));
Hero hero1 = new Hero(1, "No1");
Hero hero2 = new Hero(2, "No2");
Hero hero3 = new Hero(3, "No3");
Hero hero4 = new Hero(4, "No4");
// singleLinkList.addToRear(hero1);
// singleLinkList.addToRear(hero2);
// singleLinkList.addToRear(hero3);
System.out.println("compare(hero1, hero2) = " + heroComparator.compare(hero1, hero2));
singleLinkList.addByAttr(hero1, heroComparator);
singleLinkList.addByAttr(hero2, heroComparator);
singleLinkList.addByAttr(hero3, heroComparator);
singleLinkList.addByAttr(hero4, heroComparator);
System.out.println("反转单链表:");
SingleLinkList.inverseLinkList(singleLinkList.getHeadNode());
singleLinkList.printLinkList();
System.out.println("插入新节点");
singleLinkList.addByAttr(hero4, heroComparator);
singleLinkList.printLinkList();
System.out.println("getValidDataNums() = " + SingleLinkList.getValidDataNums(singleLinkList.getHeadNode()));
System.out.println("更新节点");
System.out.println("updateNode: " + singleLinkList.updateNode(new Hero(1, "newNo3"), heroComparator));
singleLinkList.printLinkList();
System.out.println("获取倒数第k个节点:");
System.out.println("getInverseKNode(k) = " + singleLinkList.getInverseKNode(singleLinkList.getHeadNode(), 5));
System.out.println("删除节点:");
System.out.println("deleteNode: " + singleLinkList.deleteNode(new Hero(6, ""), heroComparator));
System.out.println("deleteNode: " + singleLinkList.deleteNode(new Hero(1, ""), heroComparator));
System.out.println("deleteNode: " + singleLinkList.deleteNode(new Hero(2, ""), heroComparator));
System.out.println("deleteNode: " + singleLinkList.deleteNode(new Hero(3, ""), heroComparator));
System.out.println("deleteNode: " + singleLinkList.deleteNode(new Hero(4, ""), heroComparator));
singleLinkList.printLinkList();
}
}