直接上代码:
public class SingleLinkedListDemo {
public static void main(String[] args){
}
/**
* 这是一个链表类,每个HeroNode就是一个节点
* 在这里需要定义我们需要的链表的一些属性
* 比如此链表定义了num,name,nickname
* 当然最重要的是定义指向下一个节点的next
*/
static class HeroNode {
public int num;
public String name;
public String nickname;
public HeroNode next;
/**
* 链表类的第一个方法当然是创建链表,这里显然利用构造方法
* 对象的创建就是通过构造方法来完成,其功能主要是完成对象的初始化。
*/
public HeroNode(int num, String name, String nickname) {
this.num = num;
this.name = name;
this.nickname = nickname;
}
/**
* 接着重写一个toString方法,目的是返回对象的内容
*/
@Override
public String toString() {
return "HeroNode{" +
"num=" + num +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}
/**
* 链表类基本完成,下一步就是链表管理类,对链表进行各种操作
* 这样就分工明确,链表类只管创建对象,管理类本身没有操作,只是运用其中的方法
*/
static class SingleLinkedList {
/**
* 链表类只需定义一个头结点,它不存放具体数据,后续操作也影响不到它
* 所有定义私有
*/
private static HeroNode head = new HeroNode(0, "", "");
/**
* 第一个方法肯定是有序的添加数据,也可以叫插入
* 加入的是对象,即链表的一个部分
*/
public void addOrder(HeroNode heroNode) {
//1.我们需要一个辅助指针帮助遍历,让它成为头结点
HeroNode temp = head;
//2.需要标志flag来判断数据是否可添加
boolean flag = false;
//在将数据插入链表时,会有三种情况
//单纯的while-true 必须在每个条件下都加入break
while (true) {
//如果temp指向了null 说明链表已经到了尾部,直接退出循环
if (temp.next == null) {
break;
}
//如果temp指向的节点序号大于要插入的节点,说明找到了插入的位置
if (temp.next.num > heroNode.num) {
break;
}
//如果temp指向的节点序号等于要插入的节点,说明这个节点已经插入过
if (temp.next.num == heroNode.num) {
//那么此时我们将flag改成true,以便下文
flag = true;
break;
}
//如果三种情况都没发生,那么指针下移
temp = temp.next;
}
//如果是因为已经存在而终止循环,那么
if (flag) {
System.out.printf("已经存在%d", heroNode.num);
}
//如果是正常到了插入的位置,要进行链表独有的三方会转
else {
heroNode.next = temp.next;
temp.next = heroNode;
}
}
/**
* 添加之后是删除,这里定义的就肯定不是你想删除的对象了
* 而是你想删除对象的序号即可,即以属性代表目标
*/
public void delete(int num) {
//1.定义一个辅助指针
HeroNode temp = head;
//2.定义标志flag判断数据是否可添加
boolean flag = false;
while (true) {
//已经到了链表的最后
if (temp.next == null) {
break;
}
//找到带删除结点的前一个节点,只有这一个条件是正确的
if (temp.next.num == num) {
flag = true;
break;
}
//后移,遍历
temp = temp.next;
}
//找到了这个节点
if (flag) {
temp.next = temp.next.next;
} else {
System.out.printf("要删除的%d节点不存在", num);
}
}
/**
* 得到链表的头节点
*/
public HeroNode getHead() {
return head;
}
/**
* 得到链表的长度
* 如果操作的对象是整个链表,那么形参就需要是链表的头节点
* 同时也要定义链表管理类的一个返回头节点的方法
*/
public static int getLength(HeroNode head) {
if (head.next == null) {
return 0;
}
HeroNode temp = head.next;
boolean flag = true;
int i = 0;
while (flag) {
if (temp == null) {
flag = false;
break;
} else {
temp = temp.next;
i++;
}
}
return i;
}
/**
* 遍历显示链表
*/
public void list() {
if (head.next == null) {
System.out.println("链表为空");
return;
}
HeroNode temp = head.next;
while (true) {
//判断链表是否到最后
if (temp == null) {
break;
}
System.out.println(temp);
temp = temp.next;
}
}
/**
* 链表的翻转,面试
*/
public static void reverse(HeroNode head) {
//如果链表为空或者只有一个节点,那么就不需要翻转
if (head.next == null || head.next.next == null) {
return;
}
//辅助节点
HeroNode temp = head.next;
//创建一个新的头节点,最后再抛弃它
HeroNode next = null;
HeroNode reverseHead = new HeroNode(0, "", "");
while (temp != null) {
next = temp.next;
//每次都将temp指向新链表的最前端
temp.next = reverseHead.next;
//连接
reverseHead.next = temp;
//遍历
temp = next;
}
//最后将自己的头节点指向
head.next = reverseHead.next;
}
/**
* 查找单链表中倒数第k个元素,面试
* index表示倒数第k个元素
*/
public static HeroNode findLastIndexNode(HeroNode head, int index) {
//如果链表为空,返回null
if (head.next == null) {
return null;
}
//得到表的长度size
int size = getLength(head);
//再做个index的校验,
if (index <= 0 || index >= size) {
return null;
}
HeroNode temp = head.next;
for (int i = 0; i < size - index; i++) {
temp = temp.next;
}
return temp;
}
}
}