增强LinkedList实现瑞士轮赛制编排
前言
LinkedList底层虽然是基于链表实现,但是由于其对底层节点进行了封装,导致无法操作底层Node对象。这也为使用上带来了很多不便,比如我之前遇到的一个需求:将n个队伍按照瑞士轮进行编排,组成n/2个队伍,并且之前交过手的不能再相遇,这个需求拆分一下便是,将n个队伍按照顺序排序后,按照顺序两两组队,如果判断不能组队则跳过该队伍与下一个队伍进行匹配。以此类推直到全部匹配上为止。如果使用链表相对更简单也更容易理解。
LinkedList增强
增强的目的是为了操作内部的链表,实现寻找当前节点的下一个节点。
import java.util.*;
import java.util.function.Consumer;/*** @program: Reids* @description:* @author: Cheng Zhi* @create: 2024-09-15 14:58**/
public class JefLinkedList<E> extends AbstractList<E> {transient int size = 0;/*** Pointer to first node.* Invariant: (first == null && last == null) ||* (first.prev == null && first.item != null)*/transient Node<E> first;/*** Pointer to last node.* Invariant: (first == null && last == null) ||* (last.next == null && last.item != null)*/transient Node<E> last;/*** Constructs an empty list.*/public JefLinkedList() {}/*** Constructs a list containing the elements of the specified* collection, in the order they are returned by the collection's* iterator.** @param c the collection whose elements are to be placed into this list* @throws NullPointerException if the specified collection is null*/public JefLinkedList(Collection<? extends E> c) {this();addAll(c);}/*** Links e as first element.*/private void linkFirst(E e) {final Node<E> f = first;final Node<E> newNode = new Node<>(null, e, f);first = newNode;if (f == null)last = newNode;elsef.prev = newNode;size++;modCount++;}/*** Links e as last element.*/void linkLast(E e) {final Node<E> l = last;final Node<E> newNode = new Node<>(l, e, null);last = newNode;if (l == null)first = newNode;elsel.next = newNode;size++;modCount++;}/*** Inserts element e before non-null Node succ.*/void linkBefore(E e, Node<E> succ) {// assert succ != null;final Node<E> pred = succ.prev;final Node<E> newNode = new Node<>(pred, e, succ);succ.prev = newNode;if (pred == null)first = newNode;elsepred.next = newNode;size++;modCount++;}/*** Unlinks non-null first node f.*/private E unlinkFirst(Node<E> f) {// assert f == first && f != null;final E element = f.item;final Node<E> next = f.next;f.item = null;f.next = null; // help GCfirst = next;if (next == null)last = null;elsenext.prev = null;size--;modCount++;return element;}/*** 移除指定节点* @param node*/public void removeNode(Node<E> node) {// 获取前置节点Node<E> prev = node.prev;Node<E> next = node.next;if (prev != null) {prev.next = next;} else {// 如果前置节点为空说明是头节点removeFirst();return;}if (next != null) {size--;next.prev = prev;} else {removeLast();return;}}/*** 获取头节点* @return*/public Node<E> getFirstNode() {return first;}/*** Unlinks non-null last node l.*/private E unlinkLast(Node<E> l) {// assert l == last && l != null;final E element = l.item;final Node<E> prev = l.prev;l.item = null;l.prev = null; // help GClast = prev;if (prev == null)first = null;elseprev.next = null;size--;modCount++;return element;}/*** Unlinks non-null node x.*/E unlink(Node<E> x) {// assert x != null;final E element = x.item;final Node<E> next = x.next;final Node<E> prev = x.prev;if (prev == null) {first = next;} else {prev.next = next;x.prev = null;}if (next == null) {last = prev;} else {next.prev = prev;x.next = null;}x.item = null;size--;modCount++;return element;}/*** Returns the first element in this list.** @return the first element in this list* @throws NoSuchElementException if this list is empty*/public E getFirst() {final Node<E> f = first;if (f == null)throw new NoSuchElementException();return f.item;}/*** Returns the last element in this list.** @return the last element in this list* @throws NoSuchElementException if this list is empty*/public E getLast() {final Node<E> l = last;if (l == null)throw new NoSuchElementException();return l.item;}/*** Removes and returns the first element from this list.** @return the first element from this list* @throws NoSuchElementException if this list is empty*/public E removeFirst() {final Node<E> f = first;if (f == null)throw new NoSuchElementException();return unlinkFirst(f);}/*** Removes and returns the last element from this list.** @return the last element from this list* @throws NoSuchElementException if this list is empty*/public E removeLast() {final Node<E> l = last;if (l == null)throw new NoSuchElementException();return unlinkLast(l);}/*** Inserts the specified element at the beginning of this list.** @param e the element to add*/public void addFirst(E e) {linkFirst(e);}/*** Appends the specified element to the end of this list.** <p>This method is equivalent to {@link #add}.** @param e the element to add*/public void addLast(E e) {linkLast(e);}/*** Returns {@code true} if this list contains the specified element.* More formally, returns {@code true} if and only if this list contains* at least one element {@code e} such that* <tt>(o==null ? e==null : o.equals(e))</tt>.** @param o element whose presence in this list is to be tested* @return {@code true} if this list contains the specified element*/public boolean contains(Object o) {return indexOf(o) != -1;}/*** Returns the number of elements in this list.** @return the number of elements in this list*/public int size() {return size;}/*** Appends the specified element to the end of this list.** <p>This method is equivalent to {@link #addLast}.** @param e element to be appended to this list* @return {@code true} (as specified by {@link Collection#add})*/public boolean add(E e) {linkLast(e);return true;}/*** Removes the first occurrence of the specified element from this list,* if it is present. If this list does not contain the element, it is* unchanged. More formally, removes the element with the lowest index* {@code i} such that* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>* (if such an element exists). Returns {@code true} if this list* contained the specified element (or equivalently, if this list* changed as a result of the call).** @param o element to be removed from this list, if present* @return {@code true} if this list contained the specified element*/public boolean remove(Object o) {if (o == null) {for (Node<E> x = first; x != null; x = x.next) {if (x.item == null) {unlink(x);return true;}}} else {for (Node<E> x = first; x != null; x = x.next) {if (o.equals(x.item)) {unlink(x);return true;}}}return false;}/*** Appends all of the elements in the specified collection to the end of* this list, in the order that they are returned by the specified* collection's iterator. The behavior of this operation is undefined if* the specified collection is modified while the operation is in* progress. (Note that this will occur if the specified collection is* this list, and it's nonempty.)** @param c collection containing elements to be added to this list* @return {@code true} if this list changed as a result of the call* @throws NullPointerException if the specified collection is null*/public boolean addAll(Collection<? extends E> c) {return addAll(size, c);}/*** Inserts all of the elements in the specified collection into this* list, starting at the specified position. Shifts the element* currently at that position (if any) and any subsequent elements to* the right (increases their indices). The new elements will appear* in the list in the order that they are returned by the* specified collection's iterator.** @param index index at which to insert the first element* from the specified collection* @param c collection containing elements to be added to this list* @return {@code true} if this list changed as a result of the call* @throws IndexOutOfBoundsException {@inheritDoc}* @throws NullPointerException if the specified collection is null*/public boolean addAll(int index, Collection<? extends E> c) {checkPositionIndex(index);Object[] a = c.toArray();int numNew = a.length;if (numNew == 0)return false;Node<E> pred, succ;if (index == size) {succ = null;pred = last;} else {succ = node(index);pred = succ.prev;}for (Object o : a) {@SuppressWarnings("unchecked") E e = (E) o;Node<E> newNode = new Node<>(pred, e, null);if (pred == null)first = newNode;elsepred.next = newNode;pred = newNode;}if (succ == null) {last = pred;} else {pred.next = succ;succ.prev = pred;}size += numNew;modCount++;return true;}/*** Removes all of the elements from this list.* The list will be empty after this call returns.*/public void clear() {// Clearing all of the links between nodes is "unnecessary", but:// - helps a generational GC if the discarded nodes inhabit// more than one generation// - is sure to free memory even if there is a reachable Iteratorfor (Node<E> x = first; x != null; ) {Node<E> next = x.next;x.item = null;x.next = null;x.prev = null;x = next;}first = last = null;size = 0;modCount++;}// Positional Access Operations/*** Returns the element at the specified position in this list.** @param index index of the element to return* @return the element at the specified position in this list* @throws IndexOutOfBoundsException {@inheritDoc}*/public E get(int index) {checkElementIndex(index);return node(index).item;}/*** Replaces the element at the specified position in this list with the* specified element.** @param index index of the element to replace* @param element element to be stored at the specified position* @return the element previously at the specified position* @throws IndexOutOfBoundsException {@inheritDoc}*/public E set(int index, E element) {checkElementIndex(index);Node<E> x = node(index);E oldVal = x.item;x.item = element;return oldVal;}/*** Inserts the specified element at the specified position in this list.* Shifts the element currently at that position (if any) and any* subsequent elements to the right (adds one to their indices).** @param index index at which the specified element is to be inserted* @param element element to be inserted* @throws IndexOutOfBoundsException {@inheritDoc}*/public void add(int index, E element) {checkPositionIndex(index);if (index == size)linkLast(element);elselinkBefore(element, node(index));}/*** Removes the element at the specified position in this list. Shifts any* subsequent elements to the left (subtracts one from their indices).* Returns the element that was removed from the list.** @param index the index of the element to be removed* @return the element previously at the specified position* @throws IndexOutOfBoundsException {@inheritDoc}*/public E remove(int index) {checkElementIndex(index);return unlink(node(index));}/*** Tells if the argument is the index of an existing element.*/private boolean isElementIndex(int index) {return index >= 0 && index < size;}/*** Tells if the argument is the index of a valid position for an* iterator or an add operation.*/private boolean isPositionIndex(int index) {return index >= 0 && index <= size;}/*** Constructs an IndexOutOfBoundsException detail message.* Of the many possible refactorings of the error handling code,* this "outlining" performs best with both server and client VMs.*/private String outOfBoundsMsg(int index) {return "Index: "+index+", Size: "+size;}private void checkElementIndex(int index) {if (!isElementIndex(index))throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}private void checkPositionIndex(int index) {if (!isPositionIndex(index))throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}/*** Returns the (non-null) Node at the specified element index.*/Node<E> node(int index) {// assert isElementIndex(index);if (index < (size >> 1)) {Node<E> x = first;for (int i = 0; i < index; i++)x = x.next;return x;} else {Node<E> x = last;for (int i = size - 1; i > index; i--)x = x.prev;return x;}}// Search Operations/*** Returns the index of the first occurrence of the specified element* in this list, or -1 if this list does not contain the element.* More formally, returns the lowest index {@code i} such that* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,* or -1 if there is no such index.** @param o element to search for* @return the index of the first occurrence of the specified element in* this list, or -1 if this list does not contain the element*/public int indexOf(Object o) {int index = 0;if (o == null) {for (Node<E> x = first; x != null; x = x.next) {if (x.item == null)return index;index++;}} else {for (Node<E> x = first; x != null; x = x.next) {if (o.equals(x.item))return index;index++;}}return -1;}/*** Returns the index of the last occurrence of the specified element* in this list, or -1 if this list does not contain the element.* More formally, returns the highest index {@code i} such that* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,* or -1 if there is no such index.** @param o element to search for* @return the index of the last occurrence of the specified element in* this list, or -1 if this list does not contain the element*/public int lastIndexOf(Object o) {int index = size;if (o == null) {for (Node<E> x = last; x != null; x = x.prev) {index--;if (x.item == null)return index;}} else {for (Node<E> x = last; x != null; x = x.prev) {index--;if (o.equals(x.item))return index;}}return -1;}// Queue operations./*** Retrieves, but does not remove, the head (first element) of this list.** @return the head of this list, or {@code null} if this list is empty* @since 1.5*/public E peek() {final Node<E> f = first;return (f == null) ? null : f.item;}/*** Retrieves, but does not remove, the head (first element) of this list.** @return the head of this list* @throws NoSuchElementException if this list is empty* @since 1.5*/public E element() {return getFirst();}/*** Retrieves and removes the head (first element) of this list.** @return the head of this list, or {@code null} if this list is empty* @since 1.5*/public E poll() {final Node<E> f = first;return (f == null) ? null : unlinkFirst(f);}/*** Retrieves and removes the head (first element) of this list.** @return the head of this list* @throws NoSuchElementException if this list is empty* @since 1.5*/public E remove() {return removeFirst();}/*** Adds the specified element as the tail (last element) of this list.** @param e the element to add* @return {@code true} (as specified by {@link Queue#offer})* @since 1.5*/public boolean offer(E e) {return add(e);}// Deque operations/*** Inserts the specified element at the front of this list.** @param e the element to insert* @return {@code true} (as specified by {@link Deque#offerFirst})* @since 1.6*/public boolean offerFirst(E e) {addFirst(e);return true;}/*** Inserts the specified element at the end of this list.** @param e the element to insert* @return {@code true} (as specified by {@link Deque#offerLast})* @since 1.6*/public boolean offerLast(E e) {addLast(e);return true;}/*** Retrieves, but does not remove, the first element of this list,* or returns {@code null} if this list is empty.** @return the first element of this list, or {@code null}* if this list is empty* @since 1.6*/public E peekFirst() {final Node<E> f = first;return (f == null) ? null : f.item;}/*** Retrieves, but does not remove, the last element of this list,* or returns {@code null} if this list is empty.** @return the last element of this list, or {@code null}* if this list is empty* @since 1.6*/public E peekLast() {final Node<E> l = last;return (l == null) ? null : l.item;}/*** Retrieves and removes the first element of this list,* or returns {@code null} if this list is empty.** @return the first element of this list, or {@code null} if* this list is empty* @since 1.6*/public E pollFirst() {final Node<E> f = first;return (f == null) ? null : unlinkFirst(f);}/*** Retrieves and removes the last element of this list,* or returns {@code null} if this list is empty.** @return the last element of this list, or {@code null} if* this list is empty* @since 1.6*/public E pollLast() {final Node<E> l = last;return (l == null) ? null : unlinkLast(l);}/*** Pushes an element onto the stack represented by this list. In other* words, inserts the element at the front of this list.** <p>This method is equivalent to {@link #addFirst}.** @param e the element to push* @since 1.6*/public void push(E e) {addFirst(e);}/*** Pops an element from the stack represented by this list. In other* words, removes and returns the first element of this list.** <p>This method is equivalent to {@link #removeFirst()}.** @return the element at the front of this list (which is the top* of the stack represented by this list)* @throws NoSuchElementException if this list is empty* @since 1.6*/public E pop() {return removeFirst();}/*** Removes the first occurrence of the specified element in this* list (when traversing the list from head to tail). If the list* does not contain the element, it is unchanged.** @param o element to be removed from this list, if present* @return {@code true} if the list contained the specified element* @since 1.6*/public boolean removeFirstOccurrence(Object o) {return remove(o);}/*** Removes the last occurrence of the specified element in this* list (when traversing the list from head to tail). If the list* does not contain the element, it is unchanged.** @param o element to be removed from this list, if present* @return {@code true} if the list contained the specified element* @since 1.6*/public boolean removeLastOccurrence(Object o) {if (o == null) {for (Node<E> x = last; x != null; x = x.prev) {if (x.item == null) {unlink(x);return true;}}} else {for (Node<E> x = last; x != null; x = x.prev) {if (o.equals(x.item)) {unlink(x);return true;}}}return false;}/*** Returns a list-iterator of the elements in this list (in proper* sequence), starting at the specified position in the list.* Obeys the general contract of {@code List.listIterator(int)}.<p>** The list-iterator is <i>fail-fast</i>: if the list is structurally* modified at any time after the Iterator is created, in any way except* through the list-iterator's own {@code remove} or {@code add}* methods, the list-iterator will throw a* {@code ConcurrentModificationException}. Thus, in the face of* concurrent modification, the iterator fails quickly and cleanly, rather* than risking arbitrary, non-deterministic behavior at an undetermined* time in the future.** @param index index of the first element to be returned from the* list-iterator (by a call to {@code next})* @return a ListIterator of the elements in this list (in proper* sequence), starting at the specified position in the list* @throws IndexOutOfBoundsException {@inheritDoc}* @see List#listIterator(int)*/public ListIterator<E> listIterator(int index) {checkPositionIndex(index);return new ListItr(index);}private class ListItr implements ListIterator<E> {private Node<E> lastReturned;private Node<E> next;private int nextIndex;private int expectedModCount = modCount;ListItr(int index) {// assert isPositionIndex(index);next = (index == size) ? null : node(index);nextIndex = index;}public boolean hasNext() {return nextIndex < size;}public E next() {checkForComodification();if (!hasNext())throw new NoSuchElementException();lastReturned = next;next = next.next;nextIndex++;return lastReturned.item;}public boolean hasPrevious() {return nextIndex > 0;}public E previous() {checkForComodification();if (!hasPrevious())throw new NoSuchElementException();lastReturned = next = (next == null) ? last : next.prev;nextIndex--;return lastReturned.item;}public int nextIndex() {return nextIndex;}public int previousIndex() {return nextIndex - 1;}public void remove() {checkForComodification();if (lastReturned == null)throw new IllegalStateException();Node<E> lastNext = lastReturned.next;unlink(lastReturned);if (next == lastReturned)next = lastNext;elsenextIndex--;lastReturned = null;expectedModCount++;}public void set(E e) {if (lastReturned == null)throw new IllegalStateException();checkForComodification();lastReturned.item = e;}public void add(E e) {checkForComodification();lastReturned = null;if (next == null)linkLast(e);elselinkBefore(e, next);nextIndex++;expectedModCount++;}public void forEachRemaining(Consumer<? super E> action) {Objects.requireNonNull(action);while (modCount == expectedModCount && nextIndex < size) {action.accept(next.item);lastReturned = next;next = next.next;nextIndex++;}checkForComodification();}final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();}}public static class Node<E> {E item;Node<E> next;Node<E> prev;Node(Node<E> prev, E element, Node<E> next) {this.item = element;this.next = next;this.prev = prev;}}/*** @since 1.6*/public Iterator<E> descendingIterator() {return new DescendingIterator();}/*** Adapter to provide descending iterators via ListItr.previous*/private class DescendingIterator implements Iterator<E> {private final ListItr itr = new ListItr(size());public boolean hasNext() {return itr.hasPrevious();}public E next() {return itr.previous();}public void remove() {itr.remove();}}@SuppressWarnings("unchecked")private JefLinkedList<E> superClone() {try {return (JefLinkedList<E>) super.clone();} catch (CloneNotSupportedException e) {throw new InternalError(e);}}/*** Returns a shallow copy of this {@code LinkedList}. (The elements* themselves are not cloned.)** @return a shallow copy of this {@code LinkedList} instance*/public Object clone() {JefLinkedList<E> clone = superClone();// Put clone into "virgin" stateclone.first = clone.last = null;clone.size = 0;clone.modCount = 0;// Initialize clone with our elementsfor (Node<E> x = first; x != null; x = x.next)clone.add(x.item);return clone;}/*** Returns an array containing all of the elements in this list* in proper sequence (from first to last element).** <p>The returned array will be "safe" in that no references to it are* maintained by this list. (In other words, this method must allocate* a new array). The caller is thus free to modify the returned array.** <p>This method acts as bridge between array-based and collection-based* APIs.** @return an array containing all of the elements in this list* in proper sequence*/public Object[] toArray() {Object[] result = new Object[size];int i = 0;for (Node<E> x = first; x != null; x = x.next)result[i++] = x.item;return result;}/*** Returns an array containing all of the elements in this list in* proper sequence (from first to last element); the runtime type of* the returned array is that of the specified array. If the list fits* in the specified array, it is returned therein. Otherwise, a new* array is allocated with the runtime type of the specified array and* the size of this list.** <p>If the list fits in the specified array with room to spare (i.e.,* the array has more elements than the list), the element in the array* immediately following the end of the list is set to {@code null}.* (This is useful in determining the length of the list <i>only</i> if* the caller knows that the list does not contain any null elements.)** <p>Like the {@link #toArray()} method, this method acts as bridge between* array-based and collection-based APIs. Further, this method allows* precise control over the runtime type of the output array, and may,* under certain circumstances, be used to save allocation costs.** <p>Suppose {@code x} is a list known to contain only strings.* The following code can be used to dump the list into a newly* allocated array of {@code String}:** <pre>* String[] y = x.toArray(new String[0]);</pre>** Note that {@code toArray(new Object[0])} is identical in function to* {@code toArray()}.** @param a the array into which the elements of the list are to* be stored, if it is big enough; otherwise, a new array of the* same runtime type is allocated for this purpose.* @return an array containing the elements of the list* @throws ArrayStoreException if the runtime type of the specified array* is not a supertype of the runtime type of every element in* this list* @throws NullPointerException if the specified array is null*/@SuppressWarnings("unchecked")public <T> T[] toArray(T[] a) {if (a.length < size)a = (T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);int i = 0;Object[] result = a;for (Node<E> x = first; x != null; x = x.next)result[i++] = x.item;if (a.length > size)a[size] = null;return a;}private static final long serialVersionUID = 876323262645176354L;/*** Saves the state of this {@code LinkedList} instance to a stream* (that is, serializes it).** @serialData The size of the list (the number of elements it* contains) is emitted (int), followed by all of its* elements (each an Object) in the proper order.*/private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException {// Write out any hidden serialization magics.defaultWriteObject();// Write out sizes.writeInt(size);// Write out all elements in the proper order.for (Node<E> x = first; x != null; x = x.next)s.writeObject(x.item);}/*** Reconstitutes this {@code LinkedList} instance from a stream* (that is, deserializes it).*/@SuppressWarnings("unchecked")private void readObject(java.io.ObjectInputStream s)throws java.io.IOException, ClassNotFoundException {// Read in any hidden serialization magics.defaultReadObject();// Read in sizeint size = s.readInt();// Read in all elements in the proper order.for (int i = 0; i < size; i++)linkLast((E)s.readObject());}/*** Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>* and <em>fail-fast</em> {@link Spliterator} over the elements in this* list.** <p>The {@code Spliterator} reports {@link Spliterator#SIZED} and* {@link Spliterator#ORDERED}. Overriding implementations should document* the reporting of additional characteristic values.** @implNote* The {@code Spliterator} additionally reports {@link Spliterator#SUBSIZED}* and implements {@code trySplit} to permit limited parallelism..** @return a {@code Spliterator} over the elements in this list* @since 1.8*/@Overridepublic Spliterator<E> spliterator() {return new LLSpliterator<E>(this, -1, 0);}/** A customized variant of Spliterators.IteratorSpliterator */static final class LLSpliterator<E> implements Spliterator<E> {static final int BATCH_UNIT = 1 << 10; // batch array size incrementstatic final int MAX_BATCH = 1 << 25; // max batch array size;final JefLinkedList<E> list; // null OK unless traversedNode<E> current; // current node; null until initializedint est; // size estimate; -1 until first neededint expectedModCount; // initialized when est setint batch; // batch size for splitsLLSpliterator(JefLinkedList<E> list, int est, int expectedModCount) {this.list = list;this.est = est;this.expectedModCount = expectedModCount;}final int getEst() {int s; // force initializationfinal JefLinkedList<E> lst;if ((s = est) < 0) {if ((lst = list) == null)s = est = 0;else {expectedModCount = lst.modCount;current = lst.first;s = est = lst.size;}}return s;}public long estimateSize() { return (long) getEst(); }public Spliterator<E> trySplit() {Node<E> p;int s = getEst();if (s > 1 && (p = current) != null) {int n = batch + BATCH_UNIT;if (n > s)n = s;if (n > MAX_BATCH)n = MAX_BATCH;Object[] a = new Object[n];int j = 0;do { a[j++] = p.item; } while ((p = p.next) != null && j < n);current = p;batch = j;est = s - j;return Spliterators.spliterator(a, 0, j, Spliterator.ORDERED);}return null;}public void forEachRemaining(Consumer<? super E> action) {Node<E> p; int n;if (action == null) throw new NullPointerException();if ((n = getEst()) > 0 && (p = current) != null) {current = null;est = 0;do {E e = p.item;p = p.next;action.accept(e);} while (p != null && --n > 0);}if (list.modCount != expectedModCount)throw new ConcurrentModificationException();}public boolean tryAdvance(Consumer<? super E> action) {Node<E> p;if (action == null) throw new NullPointerException();if (getEst() > 0 && (p = current) != null) {--est;E e = p.item;current = p.next;action.accept(e);if (list.modCount != expectedModCount)throw new ConcurrentModificationException();return true;}return false;}public int characteristics() {return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;}}}
编排测试
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;/*** @program: Reids* @description: 瑞士制编排* @author: Cheng Zhi* @create: 2024-09-15 14:30**/
public class SwissOrch {private JefLinkedList<Integer> linkedList = new JefLinkedList<Integer>();private List<Integer> usedPair = new ArrayList<>();private List<Integer> result = new ArrayList<>();public SwissOrch(List<Integer> list) {linkedList.addAll(list);}public void addPlayed(List list) {usedPair.addAll(list);}public List<Integer> getResult() {return this.result;}public void pairing() {int noChangeCount = 0; // 连续长度不变的计数器while(linkedList.size() > 0) {// 记录当前链表长度int previousSize = linkedList.size();boolean succFlag = false;// 取出第一个JefLinkedList.Node<Integer> node = linkedList.getFirstNode();Integer playerA = node.item;Integer pair = null;JefLinkedList.Node<Integer> next = node;while(!succFlag) {next = next.next;if (next == null) {// 说明遍历到了最后一个break;}Integer playerB = next.item;// 这里模拟匹配到对手的对局信息pair = Integer.valueOf(playerA + "" + playerB);if (isCanPair(pair)) {// 匹配成功则删除该节点linkedList.removeNode(next);succFlag = true;break;}}if (succFlag && pair != null) {linkedList.removeNode(node);result.add(pair);}// 更新计数器if (linkedList.size() == previousSize) {noChangeCount++;} else {noChangeCount = 0; // 重置计数器}// 如果连续多次次大小不变,退出循环if (noChangeCount >= linkedList.size()) {System.out.println("连续多次没有匹配到合适的选手,说明最后两名之前已经交过手,为了保证比赛的公平性,这两人只能再次对局。");JefLinkedList.Node<Integer> next1 = node.next;if (next1 != null) {pair = Integer.valueOf(playerA + "" + next1.item);linkedList.removeNode(next1);result.add(pair);} else {System.out.println("轮空了:" + playerA);}break;}}}/*** 判断是否可以组队* @param pair* @return*/public boolean isCanPair(Integer pair) {if (usedPair.contains(pair)) {return false;}return true;}public static void main(String[] args) {LinkedList<Integer> linkedList = new LinkedList<Integer>();linkedList.add(1);linkedList.add(2);linkedList.add(3);linkedList.add(4);linkedList.add(5);linkedList.add(6);linkedList.add(7);linkedList.add(8);linkedList.add(9);linkedList.add(10);linkedList.add(11);// 模拟前几局的交手情况,本轮编排时已经交过手的不能再次交手LinkedList<Integer> played = new LinkedList<>();played.add(34); // 第三队和第四队played.add(56); // 第五队和第六队played.add(910); // 第九队和第十队SwissOrch linked = new SwissOrch(linkedList);linked.addPlayed(played);linked.pairing();System.out.println(linked.getResult());}
}
相关文章:
增强LinkedList实现瑞士轮赛制编排
前言 LinkedList底层虽然是基于链表实现,但是由于其对底层节点进行了封装,导致无法操作底层Node对象。这也为使用上带来了很多不便,比如我之前遇到的一个需求:将n个队伍按照瑞士轮进行编排,组成n/2个队伍,…...

C++编译环境(IDE)推荐及安装
IDE是什么 嗨嗨嗨,我又来水博文了 今天来给大家推荐几款好用的IDE IDE是集成开发环境(Integrated Development Environment)的缩写,是一种软件应用程序,提供了用于软件开发的各种工具和功能,包括代码编辑…...

Android 12系统源码_窗口管理(八)WindowConfiguration的作用
前言 在Android系统中WindowConfiguration这个类用于管理与窗口相关的设置,该类存储了当前窗口的显示区域、屏幕的旋转方向、窗口模式等参数,应用程序通过该类提供的信息可以更好的适配不同的屏幕布局和窗口环境,以提高用户体验。 一、类定…...
已读论文创新点合集
系列文章目录 文章目录 系列文章目录一、《LAMM: Label Alignment for Multi-Modal Prompt Learning》二、《MaPLe: Multi-modal Prompt Learning》三、《Learning to Prompt for Vision-Language Models》CoOp 一、《LAMM: Label Alignment for Multi-Modal Prompt Learning》…...
12_持久化数据结构
菜鸟:老鸟,我在处理一个项目时遇到了问题。我需要频繁地修改和查询一个数据结构,但每次修改后我都得复制整个结构,性能实在是太低了。有没有什么办法可以高效地处理这种情况? 老鸟:你提到了一个很有意思的…...

【计算机网络】IP, 以太网, ARP, DNS
IP, 以太网, ARP, DNS IP协议回顾IP地址报文格式功能介绍地址管理IP地址数量问题初识 NAT 机制通信机制IP数量的解决方案网段划分特殊IP地址 路由选择 以太网协议报文格式源MAC/目的MACMAC地址是什么MAC地址格式MAC的作用 ARPDNS初识DNSDNS主要功能DNS的查询过程 IP协议 回顾I…...

OpenCore Legacy Patcher 2.0.0 发布,83 款不受支持的 Mac 机型将能运行最新的 macOS Sequoia
在不受支持的 Mac 上安装 macOS Sequoia (OpenCore Legacy Patcher v2.0.0) Install macOS on unsupported Macs 请访问原文链接:https://sysin.org/blog/install-macos-on-unsupported-mac/,查看最新版。原创作品,转载请保留出处。 作者主…...

爆改YOLOv8|使用MobileNetV4替换yolov8的Backbone
1,本文介绍 MobileNetV4 是最新的 MobileNet 系列模型,专为移动设备优化。它引入了通用反转瓶颈(UIB)和 Mobile MQA 注意力机制,提升了推理速度和效率。通过改进的神经网络架构搜索(NAS)和蒸馏…...

C语言 | Leetcode C语言题解之第406题根据身高重建队列
题目: 题解: int cmp(const void* _a, const void* _b) {int *a *(int**)_a, *b *(int**)_b;return a[0] b[0] ? a[1] - b[1] : b[0] - a[0]; }int** reconstructQueue(int** people, int peopleSize, int* peopleColSize, int* returnSize, int** …...

【Git】初识Git
本篇文章的环境是在 Ubuntu/Linux 环境下编写的 文章目录 版本控制器Git 基本操作安装 Git创建 Git 本地仓库配置 Git认识工作区、暂存区、版本库添加文件修改文件版本回退撤销修改删除文件 版本控制器 在日常工作和学习中,老板/老师要求我们修改文档,…...

vue3 透传 Attributes
前言 Vue 3 现在正式支持了多根节点的组件,也就是片段! Vue 2.x 遵循单根节点组件的规则,即一个组件的模板必须有且仅有一个根元素。 为了满足单根节点的要求,开发者会将原本多根节点的内容包裹在一个<div>元素中&#x…...

4.接口测试基础(Jmter工具/场景二:一个项目由多个人负责接口测试,我只负责其中三个模块,协同)
一、场景二:一个项目由多个人负责接口测试,我只负责其中三个模块,协同 1.什么是测试片段? 1)就相当于只是项目的一部分用例,不能单独运行,必须要和控制器(include,模块)一…...

electron react离线使用monaco-editor
目录 1.搭建一个 electron-vite 项目 2.安装monaco-editor/react和monaco-editor 3.引入并做monaco-editor离线配置 4.react中使用 5.完整代码示例 6.monaco-editor离线配置官方说明 7.测试 1.搭建一个 electron-vite 项目 pnpm create quick-start/electron 参考链接…...

Python 的 WSGI 简单了解
从 flask 的 hello world 说起 直接讨论 WSGI,很多人可能没有概念,我们还是先从一个简单的 hello world 程序开始吧。 from flask import Flaskapp Flask(__name__)app.route("/", methods[GET]) def index():return "Hello world!&q…...

基于stm32使用ucgui+GUIBuilder开发ui实例
1 项目需求 1.1 基于Tft 触摸屏实现一个自锁按键 1.2 按键在按下后背景色需要进行变化,以凸显当前按键状态(选中or 未选中) 1.3 按键选中时对某一gpio输出低电平,非选中时输出高电平 2 移植 ucgui UCGUI的文件数量很大&#x…...

Spring扩展点系列-ApplicationContextAwareProcessor
文章目录 简介源码分析示例代码示例一:扩展点的执行顺序运行示例一 示例二:获取配置文件值配置文件application.properties内容定义工具类ConfigUtilcontroller测试调用运行示例二 示例三:实现ResourceLoaderAware读取文件ExtendResourceLoad…...
基于Keil软件实现实时时钟(江协科技HAL库)
实时时钟实验是基于江协科技STM32的HAL库工程模板创建的(可以在作品“基于江科大STM32创建的HAL库工程模板”中的结尾处获取工程模板的百度网盘链接) 复制“OLED显示”的工程文件——“4-1 OLED显示屏”,并命名为“12-2 实时时钟 ”。打开工程,把下面的程序复制到相应的文…...

dedecms靶场(四种webshell姿势)
进入靶场 姿势一:过文件管理器上传WebShell 步骤一:登录后台 /dede 步骤二:核心-》文件式管理-》文件上传-》上传一句话木马 点击 步骤三:进行蚁剑连接 姿势二:修改模板文件拿WebShell 步骤一:模板-》默认…...

PHP:强大的Web开发语言
PHP:强大的Web开发语言 一、PHP 简介及优势 PHP 的基本概念 PHP(PHP: Hypertext Preprocessor)即 “超文本预处理器”,是一种通用开源脚本语言,最初由 Rasmus Lerdorf 于 1994 年创建。它可以在服务器上执行…...

06_Python数据类型_元组
Python的基础数据类型 数值类型:整数、浮点数、复数、布尔字符串容器类型:列表、元祖、字典、集合 元组 元组(Tuple)是一种不可变的序列类型,与列表类似,但有一些关键的区别。本质:只读的列表…...

【Mini-F5265-OB开发板试用测评】显示RTC日历时钟
一、前言 本章节承接上期的【Mini-F5265-OB开发板试用测评】硬件SPI方式驱动LCD屏帖子上。灵动微官方提供的“LibSamples_MM32F5260_V0.10.2”SDK中包含一个RTC日历的参考例程,因此将该功能移植到上期工程中,即可达成在LCD屏上显示RTC日历时钟。 官方提…...

Python Day46
Task: 1.不同CNN层的特征图:不同通道的特征图 2.什么是注意力:注意力家族,类似于动物园,都是不同的模块,好不好试了才知道。 3.通道注意力:模型的定义和插入的位置 4.通道注意力后的特征图和热力…...
大数据+智能零售:数字化变革下的“智慧新零售”密码
大数据+智能零售:数字化变革下的“智慧新零售”密码 大家好,今天咱们聊聊一个火到不行的话题:大数据在智能零售中的应用。这个领域,不仅是技术的“硬核战场”,更是商业创新的风口浪尖。谁能玩转数据,谁就能掌控消费者心智,实现销售爆发。 咱们不搞枯燥学术,而是用最“…...

Redis:Hash数据类型
🌈 个人主页:Zfox_ 🔥 系列专栏:Redis 🔥 Hash哈希 🐳 ⼏乎所有的主流编程语⾔都提供了哈希(hash)类型,它们的叫法可能是哈希、字典、关联数组、映射。在Redis中&#…...

【NLP中向量化方式】序号化,亚编码,词袋法等
1.序号化 将单词按照词典排序,给定从0或者1或者2开始的序号即可,一般情况有几 个特征的单词: PAD表示填充字符,UNK表示未知字符 在这个例子中,我们可以看到我们分别将3个文本分为了4个token,每个token用左侧的词典表示…...
前端面试五之vue2基础
1.属性绑定v-bind(:) v-bind 是 Vue 2 中用于动态绑定属性的核心指令,它支持多种语法和用法,能够灵活地绑定 DOM 属性、组件 prop,甚至动态属性名。通过 v-bind,可以实现数据与视图之间的高效同…...
图像处理、图像分析和图像理解的定义、联系与区别
1. 定义 图像处理(Image Processing) 图像处理是低层操作,主要针对像素级的图像数据进行加工,目的是改善图像质量或为后续分析做准备。 典型任务:去噪、增强(如对比度调整)、锐化、边缘检测、图…...

【机器学习】支持向量机实验报告——基于SVM进行分类预测
目录 一、实验题目描述 二、实验步骤 三、Python代码实现基于SVM进行分类预测 四、我的收获 五、我的感受 一、实验题目描述 实验题目:基于SVM进行分类预测 实验要求:通过给定数据,使用支持向量机算法(SVM)实现分…...

Kafka 入门指南与一键部署
Kafka 介绍 想象一下你正在运营一个大型电商平台,每秒都有成千上万的用户浏览商品、下单、支付,同时后台系统还在记录用户行为、更新库存、处理物流信息。这些海量、持续产生的数据就像奔腾不息的河流,你需要一个强大、可靠且实时的系统来接…...
python asyncio的作用
协程是可以暂停运行和恢复运行的函数。协程函数是用async定义的函数。它与普通的函数最大的区别是,当执行的时候不会真的执行里面的代码,而是返回一个协程对象,在执行协程对象时才执行里面真正的代码。 例如代码: async def cor…...