背景:用JAVA实现单链表的所有操作(
目录
- 创建带头节点head的类SingleLinkedList.java
- 创建类SingleLinkdeListMan,用于实现对SingleLinkedlist的所有操作
- 创建头节点
- 添加节点方式一:直接添加在末尾
- 添加节点方式二:自动有序化(添加无序,但是会自动排序)
- 打印链表
- 指定有哪个头节点开始打印链表
- 修改链表节点属性(demo只改名字和绰号)
- 删除节点
- 统计节点数
- 查找倒数第K个节点
- 反转链表(改变链表结构)
- 反转打印(只打印,不改变链表结构)
- 合并两个有序的链表,合并之后依然有序
开始
- 创建带头节点head的类SingleLinkedList.java
public class SingleLinkedList {
public int no;
public String name;
public String nickName;
public SingleLinkedList next;
public SingleLinkedList(int no, String name, String nickName) {
this.no = no;
this.name = name;
this.nickName = nickName;
}
@Override
public String toString() {
return "SingleLinkedList{" +
"no=" + no +
", name='" + name + '\'' +
", nickName='" + nickName + '\'' +
'}';
}
}
-
创建类SingleLinkdeListMan,用于实现对SingleLinkedlist的所有操作
-
创建头节点
private SingleLinkedList head = new SingleLinkedList(0, "", "");
public SingleLinkedList getHead() {
return head;
}
- 添加节点方式一:直接添加在末尾
public void add(SingleLinkedList heroNode) {
SingleLinkedList temp = head;
while (temp.next != null) {
temp = temp.next;
}
temp.next = heroNode;
}
- 添加节点方式二:自动有序化(添加无序,但是会自动排序)
public void addByOrder(SingleLinkedList heroNode) {
SingleLinkedList temp = head;//临时节点
boolean flag = false;//如果有这个排名,则添加失败,并给出提示
while (true) {
if (temp.next == null) {
break;//说明只有头节点,直接添加新的节点
}
if (temp.next.no > heroNode.no) {
System.out.println("插入节点位置已经找到");
break;
} else if (temp.next.no == heroNode.no) {
flag = true;//标志节点已经存在
break;
}
temp = temp.next;//节点后移
}
if (flag) {
System.out.printf("已经存在重复的英雄编号:%d,添加失败......\n", heroNode.no);
} else {
heroNode.next = temp.next;
temp.next = heroNode;
}
}
- 打印链表
//显示链表
public void showList() {
if (head.next == null) {
System.out.println("showList:链表为空。。。");
return;
}
SingleLinkedList temp = head.next;
while (temp != null) {
System.out.println(temp);
temp = temp.next;
}
}
- 指定有哪个头节点开始打印链表
//由头遍历
public static void showListFromHead(SingleLinkedList head) {
if (head.next == null) {
System.out.println("showList:链表为空。。。");
return;
}
SingleLinkedList temp = head.next;
while (temp != null) {
System.out.println(temp);
temp = temp.next;
}
}
- 修改链表节点属性(demo只改名字和绰号)
public void update(SingleLinkedList newHeroNode) {
if (head.next == null) {
System.out.println("此链表为空。。。。。");
}
SingleLinkedList temp = head.next;
boolean flag = false;//标记是否找到要修改的节点
while (true) {
if (temp == null) {
break;//此时temp是最后一个节点
}
if (temp.no == newHeroNode.no) {
System.out.println("找到节点");
flag = true;
break;
}
temp = temp.next;//节点后移
}
if (flag) {
System.out.println("进行修改。。。。。。。。");
temp.name = newHeroNode.name;
temp.nickName = newHeroNode.nickName;
} else {
System.out.printf("不存在节点:%d........\n", newHeroNode.no);
}
}
- 删除节点
//删除
public void deleteNode(int no) {
SingleLinkedList temp = head;
boolean flag = false;//标记是否找到
while (true) {
if (temp.next == null) {//已经到最后一个节点
break;
}
if (temp.next.no == no) {
//找到
System.out.println("找到节点。。。。");
flag = true;
break;
}
temp = temp.next;
}
if (flag) {
temp.next = temp.next.next;
} else {
System.out.println("节点不存在。。。。。");
}
}
- 统计节点数
public static int countNode(SingleLinkedList head) {
if (head.next == null) {
System.out.println("countNode:链表为空...");
return 0;
}
int length = 0;
SingleLinkedList cur = head.next;//不统计头节点
while (cur != null) {
length++;
cur = cur.next;
}
return length;
}
- 查找倒数第K个节点
//查找倒数第K个节点,用lastIndex表示
//0、编写一个方法,接收head节点,同时接收一个lastIndex
//1、判断链表是否为空,为空则直接返回null
//2、获取链表长度size=countNode
//3、校验lastIndex值,lastIndex应该大于0小于等于ize
//3、遍历链表size-lastIndex
//4、返回节点
public static SingleLinkedList getLastIndexNode(SingleLinkedList head, int lastIndex) {
if (head.next == null) {
return null;
}
int size = countNode(head);//获取链表长度size=countNode
SingleLinkedList temp = head.next;
if (lastIndex <= 0 || lastIndex > size) {
System.out.println("lastIndex输入有误");
return null;
}
for (int i = 0; i < size - lastIndex; i++) {
temp = temp.next;
}
return temp;
}
- 反转链表(改变链表结构)
//反转链表
public static void reverseNode(SingleLinkedList head) {
if (head.next == null || head.next.next == null) {//链表为空或者链表只有一个节点
System.out.println("链表为空或者链表只有一个节点,请直接打印");
return;
}
SingleLinkedList newReverseNode = new SingleLinkedList(0, "", "");
SingleLinkedList cur = head.next;//指向当前节点
SingleLinkedList curNext = null;//指向cur节点的下一个节点,当cur取出节点后用来标记
while (cur != null) {
curNext = cur.next;//指向cur节点的下一个节点,当cur取出节点后用来标记
cur.next = newReverseNode.next;//取出cur指向的节点,接到newReverseNode后面
newReverseNode.next = cur;//让newReverseNode与后面的反转节点连通
cur = curNext;//让cur指向下一个节点
}
head.next = newReverseNode.next;//让head重新作为反转链表的头节点
}
- 反转打印(只打印,不改变链表结构)
//反转打印
public static void reversePrint(SingleLinkedList head) {
if (head.next == null) {
return;
}
SingleLinkedList cur = head.next;//临时变量
Stack<SingleLinkedList> stack = new Stack<SingleLinkedList>();
while (cur != null) {//入栈
stack.push(cur);
cur = cur.next;
}
while (stack.size() > 0) {
System.out.println(stack.pop());//出栈
}
}
- 合并两个有序的链表,合并之后依然有序
//合并两个有序的链表,合并之后依然有序
//newLinkNode,head1,head2
//cur1,cur1Next,cur2,cur2Next
//思路:
//1、判断传递的两链表是否为空
//2、创建一个新的链表newLinkNode,并同时创建它的尾指针lastNewLinkNode
//3、创建临时指针temp1、temp2,用来标记原链表
//4、根据编号比较大小,小的插入到newLinkNode后
public SingleLinkedList transTwoLinkToNe(SingleLinkedList head1, SingleLinkedList head2) {
if (head1.next == null) {
return head2;//若head1为空,直接返回有序链表head2
}
if (head2.next == null) {
return head1;
}
SingleLinkedList newLinkNode = null;//新的存储链表
SingleLinkedList lastNewLinkNode = null;//新的存储链表的尾部指针
SingleLinkedList temp1 = head1.next;//temp1指向head1的第一个有效节点(含头节点链表)
SingleLinkedList temp2 = head2.next;
while (temp1 != null && temp2 != null) {//当链表一个为空时退出遍历
if (temp1.no <= temp2.no) {
if (newLinkNode == null) {
newLinkNode = temp1;//初始化加载,让newLinkNode指向temp1
} else {
lastNewLinkNode.next = temp1;//让尾指针指向新的临时节点
}
lastNewLinkNode = temp1;//初始化,并让尾指针后移指向temp1
temp1 = temp1.next;//移动一次
} else {
if (newLinkNode == null) {
newLinkNode = temp2;
} else {
lastNewLinkNode.next = temp2;
}
lastNewLinkNode = temp2;
temp2 = temp2.next;
}
}
if (temp1 != null) {//将剩余的节点插入完
lastNewLinkNode.next = temp1;//直接将剩下的节点接上即可
} else {
lastNewLinkNode.next = temp2;
}
return newLinkNode;
}
}
源码:SingleLinkedList.java
public class SingleLinkedList {
public int no;
public String name;
public String nickName;
public SingleLinkedList next;
public SingleLinkedList(int no, String name, String nickName) {
this.no = no;
this.name = name;
this.nickName = nickName;
}
@Override
public String toString() {
return "SingleLinkedList{" +
"no=" + no +
", name='" + name + '\'' +
", nickName='" + nickName + '\'' +
'}';
}
}
源码:LinkedListMan.java
import java.util.Stack;
/**
* @author GodLike
* @create 2019-10-07-20:03
*/
public class LinkedListMan {
//创建头节点
private SingleLinkedList head = new SingleLinkedList(0, "", "");
public SingleLinkedList getHead() {
return head;
}
//添加节点
public void add(SingleLinkedList heroNode) {
SingleLinkedList temp = head;
while (temp.next != null) {
temp = temp.next;
}
temp.next = heroNode;
}
//显示链表
public void showList() {
if (head.next == null) {
System.out.println("showList:链表为空。。。");
return;
}
SingleLinkedList temp = head.next;
while (temp != null) {
System.out.println(temp);
temp = temp.next;
}
}
//由头遍历
public static void showListFromHead(SingleLinkedList head) {
if (head.next == null) {
System.out.println("showList:链表为空。。。");
return;
}
SingleLinkedList temp = head.next;
while (temp != null) {
System.out.println(temp);
temp = temp.next;
}
}
//第二种方式在添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名,则添加失败,并给出提示)
public void addByOrder(SingleLinkedList heroNode) {
SingleLinkedList temp = head;//临时节点
boolean flag = false;//如果有这个排名,则添加失败,并给出提示
while (true) {
if (temp.next == null) {
break;//说明只有头节点,直接添加新的节点
}
if (temp.next.no > heroNode.no) {
System.out.println("插入节点位置已经找到");
break;
} else if (temp.next.no == heroNode.no) {
flag = true;//标志节点已经存在
break;
}
temp = temp.next;//节点后移
}
if (flag) {
System.out.printf("已经存在重复的英雄编号:%d,添加失败......\n", heroNode.no);
} else {
heroNode.next = temp.next;
temp.next = heroNode;
}
}
//修改
public void update(SingleLinkedList newHeroNode) {
if (head.next == null) {
System.out.println("此链表为空。。。。。");
}
SingleLinkedList temp = head.next;
boolean flag = false;//标记是否找到要修改的节点
while (true) {
if (temp == null) {
break;//此时temp是最后一个节点
}
if (temp.no == newHeroNode.no) {
System.out.println("找到节点");
flag = true;
break;
}
temp = temp.next;//节点后移
}
if (flag) {
System.out.println("进行修改。。。。。。。。");
temp.name = newHeroNode.name;
temp.nickName = newHeroNode.nickName;
} else {
System.out.printf("不存在节点:%d........\n", newHeroNode.no);
}
}
//删除
public void deleteNode(int no) {
SingleLinkedList temp = head;
boolean flag = false;//标记是否找到
while (true) {
if (temp.next == null) {//已经到最后一个节点
break;
}
if (temp.next.no == no) {
//找到
System.out.println("找到节点。。。。");
flag = true;
break;
}
temp = temp.next;
}
if (flag) {
temp.next = temp.next.next;
} else {
System.out.println("节点不存在。。。。。");
}
}
//统计有效节点数(不包括头节点)
/**
* @return 节点数
*/
public static int countNode(SingleLinkedList head) {
if (head.next == null) {
System.out.println("countNode:链表为空...");
return 0;
}
int length = 0;
SingleLinkedList cur = head.next;//不统计头节点
while (cur != null) {
length++;
cur = cur.next;
}
return length;
}
//查找倒数第K个节点,用lastIndex表示
//0、编写一个方法,接收head节点,同时接收一个lastIndex
//1、判断链表是否为空,为空则直接返回null
//2、获取链表长度size=countNode
//3、校验lastIndex值,lastIndex应该大于0小于等于ize
//3、遍历链表size-lastIndex
//4、返回节点
public static SingleLinkedList getLastIndexNode(SingleLinkedList head, int lastIndex) {
if (head.next == null) {
return null;
}
int size = countNode(head);//获取链表长度size=countNode
SingleLinkedList temp = head.next;
if (lastIndex <= 0 || lastIndex > size) {
System.out.println("lastIndex输入有误");
return null;
}
for (int i = 0; i < size - lastIndex; i++) {
temp = temp.next;
}
return temp;
}
//反转链表
public static void reverseNode(SingleLinkedList head) {
if (head.next == null || head.next.next == null) {//链表为空或者链表只有一个节点
System.out.println("链表为空或者链表只有一个节点,请直接打印");
return;
}
SingleLinkedList newReverseNode = new SingleLinkedList(0, "", "");
SingleLinkedList cur = head.next;//指向当前节点
SingleLinkedList curNext = null;//指向cur节点的下一个节点,当cur取出节点后用来标记
while (cur != null) {
curNext = cur.next;//指向cur节点的下一个节点,当cur取出节点后用来标记
cur.next = newReverseNode.next;//取出cur指向的节点,接到newReverseNode后面
newReverseNode.next = cur;//让newReverseNode与后面的反转节点连通
cur = curNext;//让cur指向下一个节点
}
head.next = newReverseNode.next;//让head重新作为反转链表的头节点
}
//反转打印
public static void reversePrint(SingleLinkedList head) {
if (head.next == null) {
return;
}
SingleLinkedList cur = head.next;//临时变量
Stack<SingleLinkedList> stack = new Stack<SingleLinkedList>();
while (cur != null) {//入栈
stack.push(cur);
cur = cur.next;
}
while (stack.size() > 0) {
System.out.println(stack.pop());//出栈
}
}
//合并两个有序的链表,合并之后依然有序
//newLinkNode,head1,head2
//cur1,cur1Next,cur2,cur2Next
//思路:
//1、判断传递的两链表是否为空
//2、创建一个新的链表newLinkNode,并同时创建它的尾指针lastNewLinkNode
//3、创建临时指针temp1、temp2,用来标记原链表
//4、根据编号比较大小,小的插入到newLinkNode后
public SingleLinkedList transTwoLinkToNe(SingleLinkedList head1, SingleLinkedList head2) {
if (head1.next == null) {
return head2;//若head1为空,直接返回有序链表head2
}
if (head2.next == null) {
return head1;
}
SingleLinkedList newLinkNode = null;//新的存储链表
SingleLinkedList lastNewLinkNode = null;//新的存储链表的尾部指针
SingleLinkedList temp1 = head1.next;//temp1指向head1的第一个有效节点(含头节点链表)
SingleLinkedList temp2 = head2.next;
while (temp1 != null && temp2 != null) {//当链表一个为空时退出遍历
if (temp1.no <= temp2.no) {
if (newLinkNode == null) {
newLinkNode = temp1;//初始化加载,让newLinkNode指向temp1
} else {
lastNewLinkNode.next = temp1;//让尾指针指向新的临时节点
}
lastNewLinkNode = temp1;//初始化,并让尾指针后移指向temp1
temp1 = temp1.next;//移动一次
} else {
if (newLinkNode == null) {
newLinkNode = temp2;
} else {
lastNewLinkNode.next = temp2;
}
lastNewLinkNode = temp2;
temp2 = temp2.next;
}
}
if (temp1 != null) {//将剩余的节点插入完
lastNewLinkNode.next = temp1;//直接将剩下的节点接上即可
} else {
lastNewLinkNode.next = temp2;
}
return newLinkNode;
}
}
测试Demo源码:
/**
* @author GodLike
* @create 2019-10-07-20:04
*/
public class Demo {
public static void main(String[] args) {
SingleLinkedList hero1 = new SingleLinkedList(1, "1", "1");
SingleLinkedList hero3 = new SingleLinkedList(5, "5", "5");
SingleLinkedList hero4 = new SingleLinkedList(4, "4", "4");
SingleLinkedList hero2 = new SingleLinkedList(9, "9", "9");
LinkedListMan addHero = new LinkedListMan();
addHero.addByOrder(hero1);
addHero.addByOrder(hero3);
addHero.addByOrder(hero4);
/* addHero.addByOrder(hero2);*/
addHero.addByOrder(hero2);
addHero.showList();
SingleLinkedList hero5 = new SingleLinkedList(1, "1", "1");
SingleLinkedList hero6 = new SingleLinkedList(3, "3", "3");
SingleLinkedList hero7 = new SingleLinkedList(6, "6", "6");
SingleLinkedList hero8 = new SingleLinkedList(2, "2", "2");
LinkedListMan addHero2 = new LinkedListMan();
addHero2.addByOrder(hero5);
addHero2.addByOrder(hero6);
addHero2.addByOrder(hero7);
addHero2.addByOrder(hero8);
addHero2.showList();
//更新测试
/*addHero.update(new SingleLinkedList(4,"linchong","baozitou"));
addHero.showList();*/
//删除测试
/*addHero.deleteNode(2);
addHero.deleteNode(1);
addHero.showList();*/
//获取有效节点数
/* System.out.println(LinkedListMan.countNode(addHero.getHead()));*/
//返回倒数第K个节点
/* System.out.println(LinkedListMan.getLastIndexNode(addHero.getHead(),2));*/
//反转测试
/* System.out.println("..........");
LinkedListMan.reverseNode(addHero.getHead());
addHero.showList();*/
//反转打印
/*System.out.println("反转打印的结果是..........");
LinkedListMan.reversePrint(addHero.getHead());
*/
//合并测试
LinkedListMan man=new LinkedListMan();
SingleLinkedList a=man.transTwoLinkToNe(addHero.getHead(),addHero2.getHead());
System.out.println("合并的结果是:..........");
LinkedListMan.showListFromHead(a);
System.out.println("链表一");
addHero.showList();
}
}