我会将代码再进一步,并删除多个退出点。这使您可以推断对列表的影响以及返回哪个节点。
Node appendRecursive(Node head, int data) {
// By default return the same list we were given.
Node list = head;
if (list == null) {
// At end of list or list is empty.
list = new Node();
list.data = data;
} else {
// Recurse.
head.next = appendRecursive(head.next, data);
}
return list;
}
就推理而言,您通常需要使用归纳法。
- 如果列表为空 (
list == null),则创建一个新节点并成为您的列表。
- 如果列表不为空,则新列表必须是附加了新数据的列表。
鉴于上述情况,可以推断在所有情况下这都会正常运行,因为列表要么为空,要么不是。
在列表上使用递归通常被认为是低效且笨重的,因为迭代算法更适合线性结构。更好的练习是编写自己的Tree 结构,因为树非常适合递归算法。您会发现在树上递归执行所需的功能通常更容易、更优雅。
static class Tree {
Node head = null;
class Node {
Node left;
Node right;
int data;
private Node(int data) {
this.data = data;
}
}
void insert(int data) {
head = insert(head, data);
}
private Node insert(Node node, int data) {
if (node == null) {
// Empty tree becomes just the node.
return new Node(data);
} else {
// Pick the correct branch to add this data to.
if (data < node.data) {
node.left = insert(node.left, data);
} else {
node.right = insert(node.right, data);
}
}
return node;
}
private CharSequence toString(Node n) {
StringBuilder s = new StringBuilder();
if (n != null) {
// First print the tree on the left.
if (n.left != null) {
s.append(toString(n.left)).append(",");
}
// Then the data in this node.
s.append(n.data);
// Then the tree on the right.
if (n.right != null) {
s.append(",").append(toString(n.right));
}
}
return s;
}
@Override
public String toString() {
// Even toString is recursive.
StringBuilder s = new StringBuilder("{");
s.append(toString(head));
return s.append("}").toString();
}
}
public void test() {
Tree tree = new Tree();
for (int i : new int[]{6, 5, 4, 3, 2, 1}) {
tree.insert(i);
}
System.out.println(tree);
}
请注意,在 toString 方法中判断在何处添加“,”是多么简单 - 打印列表时这是一个众所周知的笨拙问题。