听说面试有考到单链表的逆序合并,所以你就算懂原理没用,人家要你写出来
网上看了看,算法有两种(不知道还有没有其他的QAQ):循环与递归 (图文讲解 超清晰的,我下面写的是用java实现的而已)
首先,来一份定义单链表code:
class Link<E> {
transient private int size = 0; // 链表大小,链表为空时size为0;
transient private Node<E> first;
transient private Node<E> last;
private static class Node<E> {
E data; // 存放节点数据
Node<E> next; // 定义节点
public Node(E element, Node<E> next) {
this.data = element;
this.next = next;
}
}
/*
* add(E e)链尾增加节点
*/
public boolean add(E e) {
linkLast(e);
return true;
}
/*
* add(int index,E e)在第index位置上插入节点
*/
public void add(int index, E e) {
checkLink(index);
if (index == size) {
linkLast(e);
} else {
linkBefore(e, index);
}
}
/*
* add(E e)的底层实现
*/
public void linkLast(E e) {
Node<E> newNode = new Node<>(e, null);
if (first == null) {
first = newNode;
last = first;
} else {
last.next = newNode;
last = newNode;
}
size++;
}
/*
* 功能同上
*/
public void linkBefore(E e, int index) {
Node<E> node = node(index - 1);
Node<E> prev = node;
node = node.next;
Node<E> newNode = new Node<>(e, node);
prev.next = newNode;
size++;
}
/*
* check链表是否index存在性,否则抛出异常
*/
public void checkLink(int i) {
if (i < 0 || i > size) {
System.out.println("异常:IndexOutOfBoundsException:i>size,i= " + i);
System.exit(-1);
}
}
/*
* 取出index节点
*/
Node<E> node(int index) {
Node<E> node = first;
for (int i = 0; i < index; i++)
node = node.next;
return node;
}
public int size() {
return size;
}
public Node<E> getFirst() {
return first;
}
@Override
public String toString() {
Node<E> p = first;
StringBuffer result = new StringBuffer();
while (p != null) {
result.append(p.data);
result.append("|");
p = p.next;
}
return result.toString();
}
/*
* 循環的方式進行鏈錶逆序:其实可以以传过来的节点作为参数, 这样更人性化,这是个把整个链表逆序的方法
*/
public boolean reverse_1() {
}
/*
* 递归方式进行链表逆序:依样画葫芦
*/
public Node<E> reverse_2(Node<E> head) {
}
}
惭愧,是仿照java.util.LinkedList自己捣鼓的,其实很多java数据结构看懂了自己也能实现,不过LinkedList是双链表,
我简化成单链表而已(LinkedList也能当成单链表使用)。
注意到了,上面最后两个方法没方法体,别急,现在奉上单链表逆转的方法:
reverse_1: 循环
reverse_2: 递归
/*
* 循環的方式進行鏈錶逆序:其实可以以传过来的节点作为参数, 这样更人性化,这是个把整个链表逆序的方法
*/
public boolean reverse_1() {
Node<E> head = getFirst();
Node<E> next, prev = null;
last = head;
for (int i = 0; i < size; i++) {
next = head.next;
head.next = prev;
prev = head;
head = next;
}
first = prev;
return true;
}
/*
* 递归方式进行链表逆序:依樣畫葫蘆
*/
public Node<E> reverse_2(Node<E> head) {
Node<E> newFirst;
if (head == null || head.next == null) {
last = first;
return first = head;
}
newFirst = reverse_2(head.next);
head.next.next = head;
head.next = null;
return newFirst;
}
加上去,就完整了。不过还有很多方法没有实现,没有问题,just do it!!!
测试代码:
public class ReverseLink {
public static void main(String[] args) {
Link l = new Link();
l.add("A");
l.add("C");
l.add(1, "B");
l.add("D");
l.add("E");
l.add("F");
System.out.println(l.size());
System.out.println(l);
// reverse_1()是用循环做的
l.reverse_1();
System.out.println(l);
// reverse_2(Node<E> node)是用递归做的
l.reverse_2(l.node(0));
System.out.println(l);
}
}
(PS: 对于泛型,还是有点不太会用,Eclipse测试代码时泛型没用的地方会有小黄灯警告的,不过运行是没有问题的。其实我更想做的是逆序合并)