双向循环链表实践
2017-08-14 16:22 猪牙哥 阅读(235) 评论(0) 编辑 收藏 举报题目:
要求实现用户输入一个数使得26个字母的排列发生变化,例如用户输入3,输出结果:
DEFGHIJKLMNOPQRSTUVWXYZABC
同时需要支持负数,例如用户输入-3,输出结果:
XYZABCDEFGHIJKLMNOPQRSTUVW
-----------------------------------------------------------------------------------------------------------------------------
首先,我们要明白什么叫双向循环链表,双向,也就是有pre和next,循环也就是首尾相连,那么我们把双向循环链表设计成这样
public class MyLoopLinkedList<E> { private Node<E> head; public MyLoopLinkedList() { super(); } /** * 添加元素,默认添加到尾部 * * @param e */ public void add(E e) { if (head == null) { head = new Node<E>(null, e, null); } else {// 将首尾相连 Node<E> n = new Node<E>(null, e, null); if (head.pre == null) {// head.pre = n; head.next = n; n.next = head; n.pre = head; } else { Node<E> last = head.pre; last.next = n; n.pre = last; n.next = head; head.pre = n; } } } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[").append(head.item).append(","); for (Node<E> n = head.next; head.next != null && n != head; n = n.next) { sb.append(n.item).append(","); } sb.deleteCharAt(sb.length() - 1).append("]"); return sb.toString(); } private static class Node<E> { E item; Node<E> pre; Node<E> next; Node(Node<E> pre, E element, Node<E> next) { this.pre = pre; this.item = element; this.next = next; } } }
这里我把第一个添加的元素作为头部,测试一下是否符合可以
public static void main(String[] args){ MyLoopLinkedList<String> list=new MyLoopLinkedList<>(); list.add("A"); list.add("B"); list.add("C"); list.add("D"); list.add("E"); list.add("F"); list.add("G"); list.add("H"); list.add("I"); list.add("J"); list.add("K"); list.add("L"); list.add("M"); list.add("N"); list.add("O"); list.add("P"); list.add("Q"); list.add("R"); list.add("S"); list.add("T"); list.add("U"); list.add("V"); list.add("W"); list.add("X"); list.add("Y"); list.add("Z"); System.out.println(list.toString()); }
输出结果:
ok,没问题,那么回到正题,要求输入一个3,就从第三个数开始读起,并且支持负数,那么我个人想到了两个解决方案
①直接改变头部,代码如下
/** * 更变头部 * * @param position */ public void changeHead(int position) { for (int i = 0; i < Math.abs(position); i++) { if (position > 0) { head = head.next; } else { head = head.pre; } } }
将上面的代码添加到MyLoopLinkedList.java里面
测试代码
public static void main(String[] args){ MyLoopLinkedList<String> list=new MyLoopLinkedList<>(); list.add("A"); list.add("B"); list.add("C"); list.add("D"); list.add("E"); list.add("F"); list.add("G"); list.add("H"); list.add("I"); list.add("J"); list.add("K"); list.add("L"); list.add("M"); list.add("N"); list.add("O"); list.add("P"); list.add("Q"); list.add("R"); list.add("S"); list.add("T"); list.add("U"); list.add("V"); list.add("W"); list.add("X"); list.add("Y"); list.add("Z"); System.out.println(list.toString()); list.changeHead(3); System.out.println(list.toString()); }
测试结果:
②添加一个成员变量,设置读取的初始位置,修改toString方法
private int readLocation = 0;//读取位置 public void setReadLocation(int readLocation) { this.readLocation = readLocation; } @Override public String toString() { StringBuilder sb = new StringBuilder(); Node<E> readNode = getReadNode(); sb.append("[").append(readNode.item).append(","); for (Node<E> n = readNode.next; readNode.next != null && n != readNode; n = n.next) { sb.append(n.item).append(","); } sb.deleteCharAt(sb.length() - 1).append("]"); return sb.toString(); } /** * 确定读取元素位置 * @return */ private Node<E> getReadNode() { Node<E> readNode = head; for (int i = 0; i < Math.abs(readLocation); i++) { if (readLocation > 0) { readNode = readNode.next; } else if (readLocation < 0) { readNode = readNode.pre; } } return readNode; }
测试代码
public static void main(String[] args){ MyLoopLinkedList<String> list=new MyLoopLinkedList<>(); list.add("A"); list.add("B"); list.add("C"); list.add("D"); list.add("E"); list.add("F"); list.add("G"); list.add("H"); list.add("I"); list.add("J"); list.add("K"); list.add("L"); list.add("M"); list.add("N"); list.add("O"); list.add("P"); list.add("Q"); list.add("R"); list.add("S"); list.add("T"); list.add("U"); list.add("V"); list.add("W"); list.add("X"); list.add("Y"); list.add("Z"); System.out.println(list.toString()); list.setReadLocation(-3); System.out.println(list.toString()); }
测试结果:
总结:两种方法我比较推荐使用第二种方法,第一种方法会导致第一次添加元素的信息掉额失,而第二种方法并没有动head成员变量,并且没有影响之前的使用