链表 单链表
链表是有序的列表,以节点的方式来存储,是链式存储。
每个节点包含data域,next域。
链表的各个检点不一定是连续存储。
链表分有头节点的链表和没有头节点的链表,根据实际的需求确定。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 package cn.Retur0;public class SingleLinkedList { public static void main (String[] args) { LinkedList ll = new LinkedList(); Node node1 = new Node(1 ); Node node2 = new Node(2 ); Node node3 = new Node(3 ); Node node4 = new Node(4 ); ll.addByOrder(node1); ll.addByOrder(node3); ll.addByOrder(node4); ll.addByOrder(node2); ll.show(); ll.delete(3 ); ll.show(); } } class LinkedList { private Node head = new Node(0 ); public void add (Node node) { Node temp = head; while (temp.next != null ) { temp = temp.next; } temp.next = node; } public void addByOrder (Node node) { Node temp = head; boolean flag = false ; while (temp.next != null ) { if (temp.next.data > node.data) break ; if (temp.next.data == node.data) { flag = true ; break ; } temp = temp.next; } if (flag) { System.out.println("data值" + node.data + "重复" ); } else { node.next = temp.next; temp.next = node; } } public void delete (int data) { Node temp = head; boolean flag = false ; while (temp != null ) { if (temp.next == null ) break ; if (temp.next.data == data) { flag = true ; break ; } temp = temp.next; } if (flag) { temp.next = temp.next.next; } else { System.out.println("节点不存在" ); } } public void show () { if (head.next == null ) { System.out.println("链表为空" ); return ; } Node temp = head.next; while (temp != null ) { System.out.println(temp); temp = temp.next; } } } class Node { public int data; public Node next; public Node (int data) { this .data = data; } @Override public String toString () { return "Node{" + "data=" + data + '}' ; } }
双向链表 管理单项链表的缺点分析:
单链表查找的方向智能式一个方向,而双向链表可以向前或向后查找。
单链表不能自我删除,需要靠辅助节点。而双向链表可以自我删除。
环形链表与约瑟夫问题 设编号为1,2,…n 的 n 个人围坐一圈,约定编号为 k(1<=n<=k) 的人从1开始报数,数到m的人出列,这个人的下一位又从1开始报数,数到m的那个人又出列,以此类推,直到所有人出列为止,由此产生一个出队编号的序列。
构建一个单向的环形链表:
先创建第一个节点,让first指向改建点,并形成环形。
后面我们每创建一个新节点,就把该节点加入到已有的环形链表中。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 package cn.Retur0.linkedlist;public class Josepfu { public static void main (String[] args) { CircleSinglyLinkedList c = new CircleSinglyLinkedList(5 ); c.count(1 ,2 ,5 ); } } class CircleSinglyLinkedList { private Boy first = null ; public CircleSinglyLinkedList (int nums) { if (nums < 1 ) throw new RuntimeException("nums的值不正确" ); Boy cur = null ; for (int i = 1 ; i <= nums; i++) { Boy boy = new Boy(i); if (i == 1 ) { first = boy; first.setNext(first); cur = first; } else { cur.setNext(boy); boy.setNext(first); cur = boy; } } } public void count (int startNo, int countNum, int nums) { if (first == null || startNo < 1 || startNo > nums) { throw new RuntimeException("参数输入有误" ); } for (int i=0 ; i<startNo-1 ; i++){ first = first.getNext(); } Boy helper = first; while (helper.getNext() != first) { helper = helper.getNext(); } while (true ){ if (helper == first) break ; for (int i=0 ; i<countNum-1 ; i++){ first = first.getNext(); helper = helper.getNext(); } System.out.println(first.getNo()+"出圈" ); first = first.getNext(); helper.setNext(first); } System.out.println("最后的boy" +first.getNo()); } public void show () { if (first == null ) throw new RuntimeException("没有boy" ); Boy cur = first; while (true ) { System.out.println(cur.getNo()); if (cur.getNext() == first) break ; cur = cur.getNext(); } } } class Boy { private int no; private Boy next; public Boy (int no) { this .no = no; } public int getNo () { return no; } public void setNo (int no) { this .no = no; } public Boy getNext () { return next; } public void setNext (Boy next) { this .next = next; } }