2019/9/16 (双链表+循环链表 + 单链表解决Joseph问题)
2019/9/16 (双链表+循环链表 + 单链表解决Joseph问题)
学习视频来源:https://www.bilibili.com/video/BV1B4411H76f?p=29
双链表
package LinkedList.doubleLinkedList;
import LinkedList.MyLinkedList;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DoubleLinkedList {
private HeroNode head;
private HeroNode tail;
private int size;
@Data
static
class HeroNode{
private int no;
private String name;
private HeroNode pre;
private HeroNode next;
public HeroNode() {
pre = null;
next = null;
}
public HeroNode(int no, String name) {
this.no = no;
this.name = name;
pre = null;
next = null;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
'}';
}
}
public HeroNode getFirst(){
return this.head;
}
public HeroNode getLast(){
return this.tail;
}
public void display(){
System.out.println("========================");
HeroNode tmp = this.head;
while(tmp!=null){
System.out.println(tmp);
tmp = tmp.next;
}
System.out.println("over=================");
}
public void addLast(HeroNode node) {
if (isEmpty()){
head = node;
}
if (isNotEmpty()){
tail.next = node;
node.pre = tail;
}
tail = node;
size++;
}
public void addByOrder(HeroNode node){
HeroNode preHead = new HeroNode();
preHead.next = this.head;
HeroNode tmp = preHead;
while(true){
if (tmp.next==null){
addLast(node);
break;
}
if (tmp.next.getNo()> node.getNo()){
if(tmp.next==head){
preHead.next=node;
node.next=head;
head.pre=node;
head = node;
size++;
}else {
node.next=tmp.next;
tmp.next.pre=node;
tmp.next=node;
node.pre=tmp;
size++;
}
break;
}
tmp = tmp.next;
}
}
public boolean isEmpty(){
return size==0;
}
public boolean isNotEmpty(){
return !isEmpty();
}
public void remove(int index){
HeroNode rmvNode = getAt(index);
if (rmvNode.pre == null){
this.head = rmvNode.next;
rmvNode.next.pre = null;
rmvNode.next = null;
return ;
}
if (rmvNode.next == null){
this.tail=rmvNode.pre;
rmvNode.pre.next = null;
rmvNode.pre = null;
return ;
}
rmvNode.pre.next = rmvNode.next;
rmvNode.next.pre = rmvNode.pre;
rmvNode = null;
}
/**
* 很骚的方法是把size右移2位,相当于处以2 在与index比较看是从前遍历还是后面
* @param index
*/
public HeroNode getAt(int index){
HeroNode tmp = this.head;
for (int i = 1; i <=index-1; i++) {
tmp = tmp.next;
}
return tmp;
}
}
双链表测试
package LinkedList.doubleLinkedList;
public class DoubleLinkedListTest {
public static void main(String[] args) {
DoubleLinkedList.HeroNode a1 = new DoubleLinkedList.HeroNode(1,"2");
DoubleLinkedList.HeroNode a2 = new DoubleLinkedList.HeroNode(2,"2");
DoubleLinkedList.HeroNode a3 = new DoubleLinkedList.HeroNode(3,"2");
DoubleLinkedList list = new DoubleLinkedList();
list.addByOrder(a1);
list.addByOrder(a3);
list.addByOrder(a2);
list.display();
System.out.println(list.getSize());
System.out.println(list.getHead());
System.out.println(list.getTail());
System.out.println(list.getAt(3));
list.remove(1);
list.display();
System.out.println(list.getHead());
System.out.println(list.getTail());
}
}
单循环链表
package LinkedList.单循环链表;
public class SingleCircleLinkedList {
private Node rear;
private int size;
static class Node{
private int num;
private Node next;
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public Node(int num) {
this.num = num;
}
}
public Node getHead(){
return this.rear.next;
}
public Node getRear() {
return rear;
}
public void setRear(Node rear) {
this.rear = rear;
}
public SingleCircleLinkedList() {
rear = null;
size = 0;
}
public int getSize() {
return size;
}
public void display(){
System.out.println("========================");
if (this.size==0){
return;
}
Node tmp = rear.next;
int counts = getSize();
while((counts--)>0){
System.out.println(tmp.getNum());
tmp = tmp.next;
}
System.out.println("============OVER============");
}
public void addLast(int data){
Node node = new Node(data);
if (size==0){
rear = node;
rear.next = rear;
size++;
return;
}
node.next = rear.next;
rear.next = node;
rear = node;
size++;
}
public void addNum(int num){
if (num<1){
System.out.println("num must >1");
return;
}
for (int i = 1; i <=num; i++) {
addLast(i);
}
}
public Node getAt(int index){
if (this.size==0){
return null;
}
Node tmp = rear;
for (int i = 1; i <=index; i++) {
tmp = tmp.next;
}
return tmp;
}
public void removeNode(int index){
if (size==0){
return ;
}
if (index>size || index<1){
return;
}
Node pre ;
if (index==1){
pre = rear;
}else {
pre = getAt(index-1);
}
Node rmvNode = pre.next;
System.out.println("getOurNum: "+rmvNode.getNum());
pre.next = rmvNode.next;
if (index==size){
rear = pre;
}
size--;
}
单链表解决Joseph问题:
解决步骤
- 需求创建一个辅助指针helper,事先指向链表尾部
- 小孩报数前,找到k的位置,先让first和helper移动(k-1)次
- 当小孩报数时,helper 和first 移动 (m-1)%size次
- 这时候,first就是要删除的节点,出圈
- 最后一个节点条件为 first = helper.
/**
* Joseph 问题为:设编号为1,2,···n的人围坐一圈,约定编号为k(1<=k<=n)的人开始报数,
* 数到m的人出列,它的下一位又从1开始报数,数到m的人又开始出列,以此类推,求出圈顺序。
*/
public void joseph(int k,int m){
if (rear ==null || k<1 || k>size){
System.out.println("输入有误");
return;
}
Node helper = rear;
Node first = rear.next;
for (int i = 1; i <k; i++) {
helper = helper.next;
first = first.next;
}
while(true){
if (helper == first){ // 最后一个节点了
break;
}
for (int i = 0; i < (m-1)%size; i++) {
helper = helper.next; // first 为删除的节点
first = first.next;
}
System.out.println("小孩出圈的位置 + "+first.getNum());
helper.next = first.next;
first = first.next;
size--;
}
System.out.println("最后留在圈中为:"+first.getNum());
}
}