单链表
头结点不可动,需要借助辅助变量来操作单向链表
// 单链表
public class SingleLinkedList {
HeroNode head = new HeroNode(0,"");
// temp 头结点不能动,temp为辅助变量
// 按添加顺序添加
public void addNode(HeroNode heroNode){
HeroNode temp = head;
while (true){
if (temp.next == null){
break;
}
temp = temp.next;
}
temp.next = heroNode;
}
public void list(){
HeroNode temp = head.next;
if (head.next == null){
System.out.println("表为空");
return;
}
while (true){
if(temp == null){
System.out.println("到达表尾部");
break;
}
System.out.println(temp);
temp = temp.next;
}
}
}
class HeroNode{
private int num;
private String name;
HeroNode next;
public HeroNode(int num, String name) {
this.num = num;
this.name = name;
}
@Override
public String toString() {
return "HeroNode{" +
"num=" + num +
", name='" + name + '\'' +
'}';
}
}
按标号添加
// 按编号顺序添加
public void addByNo(HeroNode heroNode){
HeroNode temp = head;// 使用中间变量temp帮助
while (true){
if(temp.next == null){
temp.next = heroNode;
break;
}else if(temp.next.num > heroNode.num){// 使用next的num和其比较,才能操作
heroNode.next =temp.next;// 打断重连
temp.next = heroNode;// 前驱指向插入点,插入点后驱指向原后驱
break;
}else if (temp.next.num == heroNode.num){
System.out.println("已经存在了");
break;
}
temp=temp.next;
}
}
public class SingleDemo {
public static void main(String[] args) {
HeroNode node1 = new HeroNode(1, "宋江");
HeroNode node2 = new HeroNode(2, "武松");
HeroNode node3 = new HeroNode(3, "燕青");
HeroNode node4 = new HeroNode(4, "林冲");
SingleLinkedList list = new SingleLinkedList();
list.addByNo(node3);
list.addByNo(node4);
list.addByNo(node1);
list.addByNo(node2);
list.list();
}
}
单向链表的优缺点
优点:单向链表增加删除节点简单。遍历时候不会出现死循环;
缺点:只能从头到尾遍历。只能找到后继,无法找到前驱,也就是只能一直向后走
适用于节点的增加删除。
单向链表无法向前走,当要删除某个节点时,必须遍历,通过其前一个节点来完成删除,增加操作
双向链表
约瑟夫问题
单向环形链表
创建单向环形链表
// 创建单向环形状链表
class BoyList{
BoyNode first = null;
public void addBoy(int num){
if (num<1){
System.out.println("输入有误");
return;
}
BoyNode currentBoy = null;// 中间变量 协助构成环形链表
for (int i = 1; i <= num; i++) {
BoyNode boyNode = new BoyNode(i);
if (i == 1){//单个时自环,自己指向自己
first = boyNode;
first.next = first;
currentBoy = first;
}
else {
currentBoy.next = boyNode;//添加新节点,打开原来的环
boyNode.next = first;// 末尾指向开头,闭环
currentBoy = boyNode;// 辅助变量后移,帮助之后的变量添加
}
}
}
public void list(){
if (first == null){
System.out.println("没有小孩");
return;
}
BoyNode currentBoy = first;
while (true){
System.out.println("小孩的编号"+ currentBoy.num);
if (currentBoy.next == first){
break;
}
currentBoy = currentBoy.next;
}
}
}
//孩子节点
class BoyNode{
int num;
BoyNode next;
public BoyNode(int num) {
this.num = num;
}
}
小孩出圈
public void circleBoy(int start,int m){
BoyNode currentBoy = first;
// 移动到开始位置
// 自己也要报数一次
for (int i = 0; i < start-1; i++) {
currentBoy = currentBoy.next;
}
while (true) {
// 移动到要删除节点的前一个节点
for (int i = 0; i < m - 2; i++) {
currentBoy = currentBoy.next;
}
// 输出要被删除的节点
System.out.println(currentBoy.next.num);
// 删除节点
currentBoy.next = currentBoy.next.next;
// 从删除的下一个位置开始报数
currentBoy = currentBoy.next;
if (currentBoy.next == currentBoy){// 圈中只剩一个元素
System.out.println("最后的小孩"+currentBoy.num);
break;
}
}
}