4.单向循环链表、双向循环链表以及约瑟夫环问题
SingleCircle
package com.zj.CircleLinkedList;
import com.zj.AbstractList;
/**
* 单向循环链表
*
* @author yusael
*/
public class SingleCircleLinkedList<E> extends AbstractList<E> {
private Node<E> first;
private static class Node<E> {
E element;
Node<E> next;
public Node(E element, Node<E> next) {
this.element = element;
this.next = next;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(element).append("_").append(next.element);
return sb.toString();
}
}
@Override
public void clear() {
size = 0;
first = null;
}
@Override
public E get(int index) {
return node(index).element;
}
@Override
public E set(int index, E element) {
Node<E> node = node(index);
E old = node.element;
node.element = element;
return old;
}
@Override
public void add(int index, E element) {
rangeCheckForAdd(index);
if (index == 0) {
Node<E> newFirst = new Node<>(element, first);
// 拿到最后一个节点, 上面先不要直接改first, 否则下面找节点会出现问题
Node<E> last = (size == 0) ? newFirst : node(size - 1);
last.next = newFirst;
first = newFirst;
} else {
Node<E> prev = node(index - 1);
prev.next = new Node<>(element, prev.next);
}
size++;
}
@Override
public E remove(int index) {
rangeCheck(index);
Node<E> node = first;
if (index == 0) {
if (size == 1) {
first = null;
} else {
Node<E> last = node(size - 1);
first = first.next;
last.next = first;
}
} else {
Node<E> prev = node(index - 1);
node = prev.next;
prev.next = node.next;
}
size--;
return node.element;
}
@Override
public int indexOf(E element) {
if (element == null) {
Node<E> node = first;
for (int i = 0; i < size; i++) {
if (node.element == element) return i;
node = node.next;
}
} else {
Node<E> node = first;
for (int i = 0; i < size; i++) {
if (node.element.equals(element)) return i;
node = node.next;
}
}
return ELEMENT_NOT_FOUND;
}
/**
* 根据索引找到节点
*/
private Node<E> node(int index) {
rangeCheck(index);
Node<E> node = first;
for (int i = 0; i < index; i++) {
node = node.next;
}
return node;
}
@Override
public String toString() {
StringBuilder string = new StringBuilder();
string.append("[size=").append(size).append(", ");
Node<E> node = first;
for (int i = 0; i < size; i++) {
if (i != 0) {
string.append(", ");
}
string.append(node.element);
node = node.next;
}
string.append("]");
return string.toString();
}
}
DoubleCircleLinkedList:
package com.zj.CircleLinkedList;
import com.zj.AbstractList;
import org.omg.CORBA.PUBLIC_MEMBER;
/**
* 双向链表
* @author yusael
*/
public class DoubleCircleLinkedList<E> extends AbstractList<E> {
private Node<E> first;
private Node<E> last;
//如何将循环链表威力发挥到最大
private Node<E> current; //用于指向某个结点
public void reset(){// 让current指向头结点first
current = first;
}
public E next(){//让current往后走一步
if (current == null){
return null;
}
current = current.next;
return current.element;
}
public E remove(){//删除current指向的结点,删除成功后让current指向下一个结点
if (current == null){
return null;
}
Node<E> next = current.next;
E element = remove(current);
if (size == 0){
current = null;
}else {
current = next;
}
return element;
}
private static class Node<E> {
E element;
Node<E> prev; // 指向前驱节点
Node<E> next; // 指向后继节点
public Node(Node<E> prev, E element, Node<E> next) {
this.prev = prev;
this.element = element;
this.next = next;
}
@Override
public String toString(){
StringBuilder sb = new StringBuilder();
if(prev != null){
sb.append(prev.element);
}else{
sb.append("null");
}
sb.append("_").append(element).append("_");
if(next != null){
sb.append(next.element);
}else{
sb.append("null");
}
return sb.toString();
}
}
@Override
public void clear() {
size = 0;
first = null;
last = null;
}
@Override
public E get(int index) {
return node(index).element;
}
@Override
public E set(int index, E element) {
Node<E> node = node(index);
E old = node.element;
node.element = element;
return old;
}
@Override
public void add(int index, E element) {
rangeCheckForAdd(index);
// size == 0
// index == 0
if (index == size) { // 往最后面添加元素
Node<E> oldLast = last;
last = new Node<>(oldLast, element, first);
if (oldLast == null) { // 这是链表添加的第一个元素
first = last;
first.next = first;
first.prev = first;
} else {
oldLast.next = last;
first.prev = last;
}
} else { // 正常添加元素
Node<E> next = node(index);
Node<E> prev = next.prev;
Node<E> node = new Node<>(prev, element, next);
next.prev = node;
prev.next = node;
if (index == 0) { // index == 0
first = node;
}
}
size++;
}
private E remove(Node<E> node){
if (size == 1){
first = null;
last = null;
}else {
Node<E> prev = node.prev;
Node<E> next = node.next;
prev.next = next;
next.prev = prev;
if (node == first) { // index == 0
first = next;
}
if (node == last) { // index == size - 1
last = prev;
}
}
size--;
return node.element;
}
@Override
public E remove(int index) {
rangeCheck(index);
return remove(node(index));
}
@Override
public int indexOf(E element) {
if (element == null) {
Node<E> node = first;
for (int i = 0; i < size; i++) {
if (node.element == element) return i;
node = node.next;
}
} else {
Node<E> node = first;
for (int i = 0; i < size; i++) {
if (node.element.equals(element)) return i;
node = node.next;
}
}
return ELEMENT_NOT_FOUND;
}
/**
* 根据索引找到节点
*
* @param index
* @return
*/
private Node<E> node(int index) {
rangeCheck(index);
if (index < (size >> 1)) { // 索引小于一半从前往后找
Node<E> node = first;
for (int i = 0; i < index; i++) {
node = node.next;
}
return node;
} else { // 索引大于一半从后往前找
Node<E> node = last;
for (int i = size - 1; i > index; i--) {
node = node.prev;
}
return node;
}
}
@Override
public String toString() {
StringBuilder string = new StringBuilder();
string.append("[size=").append(size).append(", ");
Node<E> node = first;
for (int i = 0; i < size; i++) {
if (i != 0) {
string.append(", ");
}
string.append(node);
node = node.next;
}
string.append("]");
return string.toString();
}
}
约瑟夫环
static void josephus(){
DoubleCircleLinkedList<Integer> list = new DoubleCircleLinkedList<>();
for (int i = 1; i <= 8; i++) {
list.add(i);
}
list.reset();
while (!list.isEmpty()){
list.next();
list.next();
System.out.println(list.remove());
}
}
Arrarylist还有可以优化的地方,每次删除元素的时候都要将所有元素前移,如果定义一个指针只记录头元素的位置就很方便。插入元素的时候,可以判断插入的位置靠前还是靠后来选择移动哪个部分的元素,再更新头指针。