一。需求
我们对在数据结构【五】- 链表【链表的介绍和实现:增删改查】中,链表的增删改查用递归的方式实现。
二。代码准备
package recursion;
import LinkedList.LinkedListRmove.ListNode;
public class LinkedList_Recursion<E> {
public class Node{
public E e;
public Node next;
public Node(Node node, E e){
this.e = e;
this.next = node;
}
public Node(){
this(null,null);
}
public Node(E e){
this(null,e);
}
@Override
public String toString() {
return e.toString();
}
}
private Node head;
private int size;
@Override
public String toString() {
StringBuilder sb = new StringBuilder("Head :");
Node curr = head;
while(curr != null){
sb.append(curr+"-> ");
curr = curr.next;
}
sb.append("NULL");
return sb.toString();
}
public LinkedList_Recursion() {
head = null;
size =0;
}
//获取元素个数
public int getSize(){
return size;
}
//判断链表时候为空
public boolean isEmpty(){
return size==0;
}
}
三。思路分析和代码实现
(一)在链表的index(0-based)位置添加新的元素e
1. 代码实现
// 在链表的index(0-based)位置添加新的元素e
public void add(int index, E e){
if(index < 0 || index > size){
throw new IllegalArgumentException("Add failed. Illegal index.");
}
head = add(head, index, e);
size++;
}
//在以node为头结点的链表的index位置插入元素e,递归算法
public Node add(Node node, int index, E e){
//递归的基本问题
if(index == 0){
return new Node(node, e);
}
node.next = add(node.next, --index, e);
return node;
}
// 在链表头添加新的元素e
public void addFirst(E e){
add(0, e);
}
// 在链表末尾添加新的元素e
public void addLast(E e){
add(size, e);
}
2. 这段递归代码的理解
//在以node为头结点的链表的index位置插入元素e,递归算法
public Node add(Node node, int index, E e){
//递归的基本问题
if(index == 0){
return new Node(node, e);
}
node.next = add(node.next, --index, e);
return node;
}
1) 递归算法的基本原则
- 求解最基本的问题:最基本的问题就是我们找到了这个index节点,然后在当前位置插入新元素。
- 更小的同一问题:给以node为头节点的链表的index位置插入元素e
2) 我们可以将这个问题这样理解【个人意见】
- 更小的同一问题:我们将原来的链表看为:【当前节点】+【已经(在index位置添加了元素)的链表】,所以我们只需要将【当前节点的next】指向【已经(在index位置添加了元素)的节点】。
- 最基本的问题:如果我们找到了index位置,就需要【要添加的节点】--> 【index位置的节点】,也就是【要添加的节点】的next指向【index位置的节点】。这样【返回的节点】就是【已经添加了新元素的节点】。代码就是【new Node(node, e);】
(二)获得链表的第index(0-based)个位置的元素
1. 代码
// 获得链表的第index(0-based)个位置的元素
public E get(int index){
if(index < 0 || index >= size){
throw new IllegalArgumentException("Get failed. Illegal index.");
}
return get(head, index);
}
//在以node为头节点的链表,获得第index个位置的元素,递归算法
public E get(Node node, int index){
//递归的基本问题
if(index ==0){
return node.e;
}
return get(node.next, --index);
}
// 获得链表的第一个元素
public E getFirst(){
return get(0);
}
// 获得链表的最后一个元素
public E getLast(){
return get(size - 1);
}
2. 这段递归代码的理解:
//在以node为头节点的链表,获得第index个位置的元素,递归算法
public E get(Node node, int index){
//递归的基本问题
if(index ==0){
return node.e;
}
return get(node.next, --index);
}
- 求解最基本的问题:最基本的问题就是我们找到了这个index节点,然后这个节点的值。
- 更小的同一问题:在以node为头结点的链表中,找到第index个元素
(三)修改链表的第index(0-based)个位置的元素为e
1. 代码
// 修改链表的第index(0-based)个位置的元素为e
public void set(int index, E e){
if(index <0 || index >= size){
throw new IllegalArgumentException("Set failed. Illegal index.");
}
set(head, index, e);
}
// 修改以node为头结点的链表中,第index(0-based)个位置的元素为e,递归算法
public void set(Node node, int index, E e){
if(index ==0){
node.e = e;
return;
}
set(node.next, --index, e);
}
2. 对其中递归的理解
- 求解最基本的问题:最基本的问题就是我们找到了这个index节点,然后改变这个节点的值。
- 更小的同一问题: 修改以node为头结点的链表中,第index(0-based)个位置的元素为e
(四)查找链表中是否有元素e
1. 代码
// 查找链表中是否有元素e
public boolean contains(E e){
return contains(head, e);
}
// 在以node为头结点的链表中,查找是否存在元素e,递归算法
public boolean contains(Node node, E e){
if(node == null){
return false;
}
if(node.e.equals(e)){
return true;
}
return contains(node.next, e);
}
2. 对其中递归的理解
递归算法的基本原则
- 求解最基本的问题:最基本的问题是含有这个节点,返回true。不含有这个值,返回false。
- 更小的同一问题: 在以node为头结点的链表中,查找是否存在元素e
(五)从链表中删除index(0-based)位置的元素, 返回删除的元素
1. 代码
// 从链表中删除index(0-based)位置的元素, 返回删除的元素
public E remove(int index){
if(index < 0 || index>=size){
throw new IllegalArgumentException("remove failed. Illegal index.");
}
Pair<Node, E> pair= remove(head, index);
head = pair.getKey();
size--;
return pair.getValue();
}
// 从以node为头结点的链表中,删除第index位置的元素,递归算法
// 返回值包含两个元素,删除后的链表头结点和删除的值;
public Pair<Node, E> remove(Node node, int index){
if(index == 0){
return new Pair<>(node.next, node.e);
}
Pair<Node,E> res = remove(node.next, --index);
node.next = res.getKey();
return new Pair<>(node, res.getValue());
}
// 从链表中删除第一个元素, 返回删除的元素
public E removeFirst(){
return remove(0);
}
// 从链表中删除最后一个元素, 返回删除的元素
public E removeLast(){
return remove(size - 1);
}
2. 对这段递归代码的理解【个人意见】:
- 求解最基本的问题:最基本的问题就是我们找到了这个index节点,然后改变这个节点的值。
- 更小的同一问题: 修改以node为头结点的链表中,第index(0-based)个位置的元素为e,递归算法
(六)从链表中删除元素e
// 从链表中删除元素e
public void removeElement(E e){
head = remove(head, e);
}
// 从以node为头结点的链表中,删除元素e,递归算法
public Node remove(Node node, E e){
if(node ==null){
return null;
}
if(node.e.equals(e)){
size--;
return node.next;
}
node.next = remove(node.next, e);
return node;
}
思路参考:数据结构【九】- 递归【二】链表的天然递归性 / 用递归解决链表中删除元素的问题 /递归算法的调式
四。代码总和
package recursion;
import LinkedList.LinkedListRmove.ListNode;
import javafx.util.Pair;
import java.util.HashMap;
public class LinkedList_Recursion<E> {
public class Node{
public E e;
public Node next;
public Node(Node node, E e){
this.e = e;
this.next = node;
}
public Node(){
this(null,null);
}
public Node(E e){
this(null,e);
}
@Override
public String toString() {
return e.toString();
}
}
private Node head;
private int size;
public LinkedList_Recursion() {
head = null;
size =0;
}
//获取元素个数
public int getSize(){
return size;
}
//判断链表时候为空
public boolean isEmpty(){
return size==0;
}
// 在链表的index(0-based)位置添加新的元素e
public void add(int index, E e){
if(index < 0 || index > size){
throw new IllegalArgumentException("Add failed. Illegal index.");
}
head = add(head, index, e);
size++;
}
//在以node为头结点的链表的index位置插入元素e,递归算法
public Node add(Node node, int index, E e){
if(index == 0){
return new Node(node, e);
}
node.next = add(node.next, --index, e);
return node;
}
// 在链表头添加新的元素e
public void addFirst(E e){
add(0, e);
}
// 在链表末尾添加新的元素e
public void addLast(E e){
add(size, e);
}
// 获得链表的第index(0-based)个位置的元素
public E get(int index){
if(index < 0 || index >= size){
throw new IllegalArgumentException("Get failed. Illegal index.");
}
return get(head, index);
}
//在以node为头节点的链表,获得第index个位置的元素,递归算法
public E get(Node node, int index){
if(index ==0){
return node.e;
}
return get(node.next, --index);
}
// 获得链表的第一个元素
public E getFirst(){
return get(0);
}
// 获得链表的最后一个元素
public E getLast(){
return get(size - 1);
}
// 修改链表的第index(0-based)个位置的元素为e
public void set(int index, E e){
if(index <0 || index >= size){
throw new IllegalArgumentException("Set failed. Illegal index.");
}
set(head, index, e);
}
// 修改以node为头结点的链表中,第index(0-based)个位置的元素为e,递归算法
public void set(Node node, int index, E e){
if(index ==0){
node.e = e;
return;
}
set(node.next, --index, e);
}
// 查找链表中是否有元素e
public boolean contains(E e){
return contains(head, e);
}
// 在以node为头结点的链表中,查找是否存在元素e,递归算法
public boolean contains(Node node, E e){
if(node == null){
return false;
}
if(node.e.equals(e)){
return true;
}
return contains(node.next, e);
}
// 从链表中删除index(0-based)位置的元素, 返回删除的元素
public E remove(int index){
if(index < 0 || index>=size){
throw new IllegalArgumentException("remove failed. Illegal index.");
}
Pair<Node, E> pair= remove(head, index);
head = pair.getKey();
size--;
return pair.getValue();
}
// 从以node为头结点的链表中,删除第index位置的元素,递归算法
// 返回值包含两个元素,删除后的链表头结点和删除的值;
public Pair<Node, E> remove(Node node, int index){
if(index == 0){
return new Pair<>(node.next, node.e);
}
Pair<Node,E> res = remove(node.next, --index);
node.next = res.getKey();
return new Pair<>(node, res.getValue());
}
// 从链表中删除第一个元素, 返回删除的元素
public E removeFirst(){
return remove(0);
}
// 从链表中删除最后一个元素, 返回删除的元素
public E removeLast(){
return remove(size - 1);
}
// 从链表中删除元素e
public void removeElement(E e){
head = remove(head, e);
}
// 从以node为头结点的链表中,删除元素e,递归算法
public Node remove(Node node, E e){
if(node ==null){
return null;
}
if(node.e.equals(e)){
size--;
return node.next;
}
node.next = remove(node.next, e);
return node;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("Head :");
Node curr = head;
while(curr != null){
sb.append(curr.e+"-> ");
curr = curr.next;
}
sb.append("NULL");
return sb.toString();
}
public static void main(String[] args) {
LinkedList_Recursion<Integer> list = new LinkedList_Recursion<>();
for(int i = 0 ; i < 5 ; i ++){
list.addFirst(i);
}
System.err.println(list);
list.add(3,7);
list.add(4,6);
list.add(2,3);
System.err.println(list);
list.removeElement(3);
list.remove(5);
System.err.println(list);
System.err.println("是否含有7:"+list.contains(7));
System.err.println("是否含有3:"+list.contains(3));
list.set(4,11);
System.err.println(list);
System.err.println("位置2的元素值:"+list.get(2));
}
}
五。测试代码
public static void main(String[] args) {
LinkedList_Recursion<Integer> list = new LinkedList_Recursion<>();
for(int i = 0 ; i < 5 ; i ++){
list.addFirst(i);
}
System.err.println(list);
list.add(3,7);
list.add(4,6);
list.add(2,3);
System.err.println(list);
list.removeElement(3);
list.remove(5);
System.err.println(list);
System.err.println("是否含有7:"+list.contains(7));
System.err.println("是否含有3:"+list.contains(3));
list.set(4,11);
System.err.println(list);
System.err.println("位置2的元素值:"+list.get(2));
}
Head :4-> 3-> 2-> 1-> 0-> NULL
Head :4-> 3-> 3-> 2-> 7-> 6-> 1-> 0-> NULL
Head :4-> 3-> 2-> 7-> 6-> 0-> NULL
是否含有7:true
是否含有3:true
Head :4-> 3-> 2-> 7-> 11-> 0-> NULL
位置2的元素值:2