今天晚上,觉得有点时间,仔细想了下,应该采用面向对象的思想,对节点和链表高度抽象,节点应可以是任意对象。
首先让我们来复习下什么是链表?我们用一个简单的示意图表示(用画图板画了个,将就看吧:)):

从上头可以看出,链表有如下特点:
1、有一个头和一个尾,一个有多个节点组成的非封闭的链
2、每个节点都有一个指针指向下一个节点
嗯,那我们要抽象一个链表的类,还要有一个节点的类,来实现上述链表的特点。
代码如下:
package com.iteye.redhacker.test; /** * 链表节点类 * * @author JackDou * @since 2013-08-11 */ public class Node { private Object value; private Node next; private int index; public Node(Object value) { this.value = value; } /** * @return the value */ public Object getValue() { return value; } /** * @param value * the value to set */ public void setValue(Object value) { this.value = value; } /** * @return the index */ public int getIndex() { return index; } /** * @param index * the index to set */ public void setIndex(int index) { this.index = index; } /** * @return the next */ public Node getNext() { return next; } /** * @param next * the next to set */ public void setNext(Node next) { this.next = next; } @Override public String toString() { return "Node [index=" + index + "," + "value=" + value + "]"; } }
package com.iteye.redhacker.test; /** * 链表类 * * @author JackDou * @since 2013-08-11 */ public class LinkedList { /** 默认容量大小及链表容量满的时候每次自动增加的大小 */ private static final int DEFAULT_CAPACITY_SIZE = 12; /** 链表中的节点集合 */ private Node[] nodes; /** 指针,指向链表末端待添加的位置,默认指向0的位置 */ private int endPos = 0; /** 当前链表容量 */ private int capacity = 0; public LinkedList() { nodes = new Node[DEFAULT_CAPACITY_SIZE]; capacity = DEFAULT_CAPACITY_SIZE; } public LinkedList(int capacity) { nodes = new Node[capacity]; this.capacity = capacity; } /** * 链表大小 * * @return 链表大小 */ public int size() { return endPos; } public int capacity() { return this.nodes.length; } /** * 向链表中加入一个节点 * * @param node 新加入的节点 */ public void add(Node node) { if (this.endPos >= this.capacity() - 1) { capacity = this.endPos + 1 + DEFAULT_CAPACITY_SIZE; Node[] nodesTemp = new Node[capacity]; System.arraycopy(nodes, 0, nodesTemp, 0, this.endPos); nodes = nodesTemp; } if (endPos == 0) { node.setIndex(0); nodes[endPos] = node; } else if (endPos > 0 && endPos <= this.capacity() - 1) { node.setIndex(endPos); nodes[endPos] = node; nodes[endPos-1].setNext(nodes[endPos]); } endPos++; } /** * 删除链表元素 * * @param index 要删除链表中节点的位置 */ public void remove(int index) { if (index > this.capacity() - 1 || index >= this.endPos || index < 0) { throw new RuntimeException("没有位置索引" + index + "存在"); } if (index == endPos-1) { nodes[index] = null; return; } for (; 0 <= index && index < endPos-1; index++) { if (index == 0) { nodes[index] = nodes[index+1]; nodes[index].setIndex(index); } else { nodes[index] = nodes[index+1]; nodes[index].setIndex(index); nodes[index-1].setNext(nodes[index]); } } endPos--; } /** * 更新指定链表位置节点的值 * * @param index 指定的链表位置 * @param value 指点链表位置上的节点的值 */ public void update(int index, Object value) { if (index > this.capacity() - 1 || index >= this.endPos || index < 0) { throw new RuntimeException("没有位置索引" + index + "存在"); } nodes[index].setValue(value); } /** * 获取指点链表位置上的节点的值 * * @param index 指定的链表位置 * @return 指点链表位置上的节点 */ public Node getNode(int index) { if (index > this.capacity() - 1 || index >= this.endPos || index < 0) { throw new RuntimeException("没有位置索引" + index + "存在"); } return nodes[index]; } /** * 在链表指定位置插入节点 * * @param index 指定的链表位置 * @param value 节点 */ public void insert(int index, Node node) { if (index > this.capacity() - 1 || index >= this.endPos || index < 0) { throw new RuntimeException("没有位置索引" + index + "存在"); } if (this.endPos >= this.capacity() - 1) { capacity = this.endPos + 1 + DEFAULT_CAPACITY_SIZE; Node[] nodesTemp = new Node[capacity]; System.arraycopy(nodes, 0, nodesTemp, 0, this.endPos); nodes = nodesTemp; } Node[] nodesTemp = new Node[size()- index]; System.arraycopy(nodes, index, nodesTemp, 0, nodesTemp.length); for (int i = 0, len= nodesTemp.length; i< len; i++) { nodesTemp[i].setIndex(nodesTemp[i].getIndex() + 1); } endPos++; node.setIndex(index); System.arraycopy(nodesTemp, 0, nodes, index+1, nodesTemp.length); node.setNext(nodes[0]); nodes[index] = node; nodes[index-1].setNext(nodes[index]); nodes[index].setNext(nodes[index+1]); } /** * 获取链表的第一个节点 * * @return 链表的第一个节点 */ public Node getFirst() { return nodes[0]; } /** * 获取链表的最后一个节点 * * @return 链表的最后一个节点 */ public Node getLast() { return nodes[endPos-1]; } /** * 链表反序 */ public LinkedList reverse() { Node[] nodesTemp = new Node[capacity]; for (int i = 0, j = endPos - 1; i < endPos && j >= 0; i++, j--) { nodesTemp[i] = nodes[j]; nodesTemp[i].setIndex(i); if (j > 0) { nodesTemp[i].setNext(nodes[j-1]); } } nodes = nodesTemp; return this; } public String toString() { StringBuilder strBui = new StringBuilder(); for (int i = 0; i < endPos; i++) { strBui.append(nodes[i].toString()); if (i < endPos) { strBui.append(","); } } return strBui.toString(); } /** * 获取当前链表容量 * * @return the capacity */ public int getCapacity() { return capacity; } }
package com.iteye.redhacker.test; /** * 测试类 * * @author JackDou * @since 2013-08-11 */ public class Test { public static void main(String[] args) { // 创建默认大小的LinkedList LinkedList list1 = new LinkedList(); list1.add(new Node(12)); list1.add(new Node(10)); list1.add(new Node(11)); list1.add(new Node(8)); list1.add(new Node(9)); System.out.println("链表默认容量为12"); System.out.println("链表长度:" + list1.size()); System.out.println("链表当前容量:" + list1.getCapacity()); System.out.println(); list1.add(new Node(2)); list1.add(new Node(4)); list1.add(new Node(5)); list1.add(new Node(7)); list1.add(new Node(6)); list1.add(new Node(1)); list1.add(new Node(3)); System.out.println("链表容量满时会自动扩容,默认为扩大12个节点容量"); System.out.println("链表:" + list1.toString()); System.out.println("链表第一个节点:" + list1.getFirst()); System.out.println("链表最后一个节点节点:" + list1.getLast()); System.out.println("链表长度:" + list1.size()); System.out.println("链表当前容量:" + list1.getCapacity()); System.out.println(); list1.remove(3); System.out.println("删除索引为3的节点后的情况:"); System.out.println("链表:" + list1.toString()); System.out.println("链表第一个节点:" + list1.getFirst()); System.out.println("链表最后一个节点节点:" + list1.getLast()); System.out.println("链表长度:" + list1.size()); System.out.println("链表当前容量:" + list1.getCapacity()); System.out.println(); list1.add(new Node(80)); list1.add(new Node(90)); System.out.println("新增两个节点的情况(新增:80,90两个数字):"); System.out.println("链表:" + list1.toString()); System.out.println("链表第一个节点:" + list1.getFirst()); System.out.println("链表最后一个节点节点:" + list1.getLast()); System.out.println("链表长度:" + list1.size()); System.out.println("链表当前容量:" + list1.getCapacity()); System.out.println(); System.out.println("获取第8个节点的信息:" + list1.getNode(8)); System.out.println("获取第8个节点的下一个节点信息是:" + list1.getNode(8).getNext()); System.out.println(); System.out.println("测试反序链表"); System.out.println("原链表:" + list1.toString()); System.out.println("反序链表:" + list1.reverse().toString()); System.out.println(); System.out.println("链表长度:" + list1.size()); System.out.println("链表当前容量:" + list1.getCapacity()); System.out.println("测试在第3个索引的位置连续插入12个值为45的节点,使得链表长度超过当前容量,测试链表的自增长容量"); System.out.println("原链表:" + list1.toString()); list1.insert(3, new Node(45)); list1.insert(3, new Node(45)); list1.insert(3, new Node(45)); list1.insert(3, new Node(45)); list1.insert(3, new Node(45)); list1.insert(3, new Node(45)); list1.insert(3, new Node(45)); list1.insert(3, new Node(45)); list1.insert(3, new Node(45)); list1.insert(3, new Node(45)); list1.insert(3, new Node(45)); list1.insert(3, new Node(45)); System.out.println("插入后链表:" + list1.toString()); System.out.println("链表长度:" + list1.size()); System.out.println("链表当前容量:" + list1.getCapacity()); } }
测试类打印出来的结果是:
引用
链表默认容量为12
链表长度:5
链表当前容量:12
链表容量满时会自动扩容,默认为扩大12个节点容量
链表:Node [index=0,value=12],Node [index=1,value=10],Node [index=2,value=11],Node [index=3,value=8],Node [index=4,value=9],Node [index=5,value=2],Node [index=6,value=4],Node [index=7,value=5],Node [index=8,value=7],Node [index=9,value=6],Node [index=10,value=1],Node [index=11,value=3],
链表第一个节点:Node [index=0,value=12]
链表最后一个节点节点:Node [index=11,value=3]
链表长度:12
链表当前容量:24
删除索引为3的节点后的情况:
链表:Node [index=0,value=12],Node [index=1,value=10],Node [index=2,value=11],Node [index=3,value=9],Node [index=4,value=2],Node [index=5,value=4],Node [index=6,value=5],Node [index=7,value=7],Node [index=8,value=6],Node [index=9,value=1],Node [index=10,value=3],
链表第一个节点:Node [index=0,value=12]
链表最后一个节点节点:Node [index=10,value=3]
链表长度:11
链表当前容量:24
新增两个节点的情况(新增:80,90两个数字):
链表:Node [index=0,value=12],Node [index=1,value=10],Node [index=2,value=11],Node [index=3,value=9],Node [index=4,value=2],Node [index=5,value=4],Node [index=6,value=5],Node [index=7,value=7],Node [index=8,value=6],Node [index=9,value=1],Node [index=10,value=3],Node [index=11,value=80],Node [index=12,value=90],
链表第一个节点:Node [index=0,value=12]
链表最后一个节点节点:Node [index=12,value=90]
链表长度:13
链表当前容量:24
获取第8个节点的信息:Node [index=8,value=6]
获取第8个节点的下一个节点信息是:Node [index=9,value=1]
测试反序链表
原链表:Node [index=0,value=12],Node [index=1,value=10],Node [index=2,value=11],Node [index=3,value=9],Node [index=4,value=2],Node [index=5,value=4],Node [index=6,value=5],Node [index=7,value=7],Node [index=8,value=6],Node [index=9,value=1],Node [index=10,value=3],Node [index=11,value=80],Node [index=12,value=90],
反序链表:Node [index=0,value=90],Node [index=1,value=80],Node [index=2,value=3],Node [index=3,value=1],Node [index=4,value=6],Node [index=5,value=7],Node [index=6,value=5],Node [index=7,value=4],Node [index=8,value=2],Node [index=9,value=9],Node [index=10,value=11],Node [index=11,value=10],Node [index=12,value=12],
链表长度:13
链表当前容量:24
测试caruso元素到第3个索引的位置连续插入12个值为45的节点,使得链表长度超过当前容量,测试链表的自增长容量
原链表:Node [index=0,value=90],Node [index=1,value=80],Node [index=2,value=3],Node [index=3,value=1],Node [index=4,value=6],Node [index=5,value=7],Node [index=6,value=5],Node [index=7,value=4],Node [index=8,value=2],Node [index=9,value=9],Node [index=10,value=11],Node [index=11,value=10],Node [index=12,value=12],
插入后链表:Node [index=0,value=90],Node [index=1,value=80],Node [index=2,value=3],Node [index=3,value=45],Node [index=4,value=45],Node [index=5,value=45],Node [index=6,value=45],Node [index=7,value=45],Node [index=8,value=45],Node [index=9,value=45],Node [index=10,value=45],Node [index=11,value=45],Node [index=12,value=45],Node [index=13,value=45],Node [index=14,value=45],Node [index=15,value=1],Node [index=16,value=6],Node [index=17,value=7],Node [index=18,value=5],Node [index=19,value=4],Node [index=20,value=2],Node [index=21,value=9],Node [index=22,value=11],Node [index=23,value=10],Node [index=24,value=12],
链表长度:25
链表当前容量:36
关于程序的详细实现这里不做详细的解释了,大家可以直接从文后下到源码,到如到eclipse里自行学习。
值得要说明的是:
1、我在链表里实现了一个反序,这是当时被问及的关键点,现在看起来似乎很简单的;
2、我在这个实现里使用了System.arraycopy()这个高级的API,或许还不够原生,有系统的同学可以实现自己的数组拷贝方法用以代替。
我的算法的复习因以此契机还需继续,希望有更多的时间去思考这些问题。加油!