一.双向链表
单向链表,查找的方向只能是一个方向,而双向链 表可以向前或者向后查找
单向链表不能自我删除,需要靠辅助节点 ,而双向 链表,则可以自我删除,单链表删除时节点,总是找到temp,temp是待删除节点的前一 个节点
双向链表自我删除
- temp.pre.next = temp.next
- temp.next.pre = temp.pre
1.双向链表添加节点
public void add(HeroNode1 heroNode) {
//头节点不能动
HeroNode1 temp = head;
while (true) {
if (temp.next == null) {
break;
}
temp = temp.next;
}
temp.next = heroNode;
heroNode.pre = temp;
}
需要让新增节点的pre指向前一个节点
2.双向链表遍历
public void list() {
//头节点不能动
HeroNode1 temp = head.next;
if (head.next == null) {
System.out.println("该链表为空");
return;
}
while (true) {
if (temp == null) {
break;
}
System.out.println(temp);
temp = temp.next;
}
}
与单向链表基本一致
3.双向链表修改
public void update(HeroNode1 heroNode) {
if (head.next == null) {
return;
}
HeroNode1 temp = head.next;
boolean flag = false;
while (true) {
if (temp == null) break;
if (temp.no == heroNode.no) {
flag = true;
break;
}
temp = temp.next;
}
if (flag) {
temp.nickName = heroNode.nickName;
temp.name = heroNode.name;
} else System.out.printf("未找到 %d \n", heroNode.no);
}
与单链表基本一致
4.双向链表删除操作
public void delete(int no) {
HeroNode1 temp = head.next;
boolean flag = false;
while (true) {
if (temp == null) break;
if (temp.no == no) {
flag = true;
break;
}
temp = temp.next;
}
if (flag) {
temp.pre.next = temp.next;
if (temp.next != null) temp.next.pre = temp.pre;
} else System.out.printf("此编号 %d 不存在", no);
}
二.单向环形链表
应用场景:Josephu(约瑟夫、约瑟夫环) 问题 Josephu 问题为:设编号为 1,2,… n 的 n 个人围坐一圈,约定编号为 k(1<=k<=n)的人从 1 开始报数,数 到 m 的那个人出列,它的下一位又从 1 开始报数,数到 m 的那个人又出列,依次类推,直到所有人出列为止,由 此产生一个出队编号的序列。
算法分析:n=5 有五个人 k=1 从第一个人开始报数 m=2 每次数三下
出圈顺序为->24153
1.将first指向圈首的节点上
2.创建一个辅助变量helper,使其指向圈的最后一个节点
3.报数前让first和helper移动k-1次
for (int i = 0; i < startNo - 1; i++) {
helper = helper.getNext();
first = first.getNext();
}
4.当此节点开始报数first和helper向后移动m-1个节点
while (true){
//圈中只有一个节点
if (helper==first) break;
for (int i = 0; i < contNum-1; i++) {
helper = helper.getNext();
first = first.getNext();
}
System.out.printf("编号: %d 出圈\n",first.getNo());
first=first.getNext();
helper.setNext(first);
}
System.out.printf("编号: %d 留在圈\n ",helper.getNo());