Data structure -- [for the understanding of recursion, use recursion to delete the elements of the linked list]

recursion

The method used calls itself in its own method body,
In essence, it is to transform the original problem into a smaller one.

For example, the method A is executed, but the method B is invoked in the method A, and the method C is invoked in the method B.

In the idea of recursion, a method calls itself directly or indirectly

For example, calculate the sum of 1 + 2 + 3 + 4 + 5... + 100;

sum(1)  =  1
sum(2)  =  2 + sum(1) = 3
sum(3)  =  3 + sum(2) = 6
sum(4)  =  4 + sum(3) = 10
........
sum(100)= 100 +sum(99)=?

Namely
sum (n)  =  n + sum(n-1)

For recursion, we should first determine the situation of a recursion to the end; (usually use if statement to judge first)

For example, when this integer is added, the recursive end point is added to 1;
After determining the end point, write the recursive method (expression),

//Integer addition;
    public static int  sum(int n) {
        //Recursive end point;;
        if(n == 1){
          return  1;
        }
        //Recursive function sum(n-1) + n
        return  sum(n-1) + n;
    }

Recursive solution of monkey eating peach problem

A monkey is eating peaches, After eating half the peaches every day,And secretly eat one more;
Results on day 6,There is only one peach left;

that;
Total peaches on day 4 ==>  1 A peach;
Total peaches on day 3  ==>  (Peaches on the fourth day +  1)  X  2  ==> 4
 Total peaches on day 2  ==>  (Peaches on the third day +  1)  X  2  ==> 10
 Total peaches on day 1  ==>  (Peaches the next day +  1)  X  2  ==> 22
......
The first n day ==> (The first (n-1) day + 1 ) ) X2
//Peach eating problem; Find the number of peaches on the first day;
public static  int peach(int day){
    //The end point of recursion is the fourth day;
    if(day == 4){
        return 1 ;
    }
    //Recursive expression;
    return (peach(day+1)+1)*2;
}

In this way, if you want to change the number of days to eat peaches, you also need to change the judgment condition of the recursive end point inside the recursive function

If the recursive end condition is changed to the penultimate day in the reverse way, there will be a peach left;

public static int peach2(int day){
     //Endpoint;
     if(day==1){
       return 1;
     }
     return (peach2(day-1)+1)*2;
 }

Recursive solution of Fibonacci number

Fibonacci sequence

The sequence starts from item 3, and each item is equal to the sum of the first two items.

public  static int test3(int i){
     //Endpoint;
     if(i==0){
         return 0;
     }
     if(i==1||i==2){
         return 1;
     }
     return test3(i-1)+test3(i-2);
 }

The deletion of the specified content of the linked list can also be realized by recursion;

Previously created custom linked list = = > MyLink
Now add a method removeValDg that uses recursion to delete the specified data element

public class MyLink<T> {
    /**
     * Create node inner class
     */
    class Node {
        //val data field;
        private T val;
        //Next refers to the reference of the next node; Default to null;
        private Node next;

        //Initialize nodes;
        public Node(T val) {
            this.val = val;
            this.next = null;
        }

        //Node data, output method;
        @Override
        public String toString() {
            return this.val.toString();
        }
    }

    //Define the chain header;
    private Node head;
    //The actual number of nodes in the linked list;
    private int size;

    //Initialize the linked list;
    public MyLink() {
        this.head = null;
        this.size = 0;
    }

    /**
     * Judge whether the linked list is empty;
     */
    public boolean isEmpty() {
        return this.size == 0;
    }
    /**
     * Get the number of nodes in the linked list;
     */
    public int getSize() {
        return this.size;
    }
    /**
     * Output linked list;
     */
    @Override
    public String toString() {

        StringBuilder sbl = new StringBuilder();
        Node cur = head;
        //Except that the head node is not empty, traverse to get all nodes;
        while (cur != null) {
            sbl.append(cur + "==>");
            cur = cur.next;
        }
        sbl.append("null");
        return sbl.toString();
    }
    //==========================================================>
    //Recursive deletion method provided for external access;
    //(note that only the first occurrence of the specified element can be deleted)
    public Node removeValDg(T val) {
        //First judge whether the linked list is empty;
        if (this.isEmpty()) {
            return null;
        }
        //Call the internally defined private method for processing;
       return head = removeValDg(head,val);
    }

    //Recursively delete the bottom layer;
    private Node removeValDg(Node head, T val) {
        //Provide termination conditions;
        if(head==null){
            return null;
        }
        //expression;
        //First, the head node to be used each time is separated from the linked list and stored in the node to be operated;
        Node operNode=head;
        //Save the next bit of the current header node as a new header node;
        Node newHead=head.next;
        //Each time the current operation node is compared, if it matches, it will be deleted and the remaining nodes will be returned;
        if(operNode.val==val){
            return newHead;
        }else{
            //If the current header node does not match, the prepared new header node will be passed into the call again; The linked list left after the final deletion shall be connected to the back of the operation node; Callback step by step;
            operNode.next=removeValDg(newHead,val);
            return operNode;
        }
    }

Note that the termination condition is head==null; This is triggered when the passed in parameter is null;

Since the operNode (current operation node) 11 does not match the deleted value, pass the newHead () to the head node (12) of the remaining linked list and call the deletion method;
It should be noted that the return linked list obtained after calling the delete method for the linked list with 12 as the head node is connected to the next bit of the previous operation node 11; in other words,
Even if it doesn't conform to the list 11 just now, you have to let it connect back; Therefore, return operNode is returned;

Then, look at the linked list with 12 as the operation node. At this time, 12 as the operNode (current operation node) needs to be separated from the remaining linked list; The operNode (current operation node) 12 needs to be taken out separately and compared with 4; Then (the head node of the remaining linked list) newHead is 13; Because the operNode (current operation node) 12 does not match the deleted value; Then, pass newHead () to the head node 13) of the remaining linked list and call the delete method; Similarly, the return linked list obtained after calling the delete method for the linked list with 13 as the head node is connected behind the previous operation node 12; The last time it was connected behind 11;
By analogy, the linked list with 13 as the operation node,... The linked list with 4 as the operation node;
In fact, this ensures that the remaining elements remain connected after the elements are finally deleted;

After testing, this method can only delete the specified element that appears for the first time;

debug debugging found that the method ended after matching to 12 as the deleted element

Let's see how to delete all specified elements in the linked list;
Direct method;

//(provided for external access) delete all specified elements of the linked list;
    public Node removeAllValDg(T val) {
        //First judge whether the linked list is empty;
        if (this.isEmpty()) {
            return null;
        }
        //Call the internally defined private method for processing;
        return head = removeAllValDg(head,val);
    }

    //Recursively delete the bottom layer of all specified element methods;
    private Node removeAllValDg(Node head, T val) {
        //Termination method;
        if(head==null){
            return null;
        }
        Node result = removeAllValDg(head.next,val);
        //Each time the current operation node is compared, if it meets the requirements, it will be deleted;
        if(head.val == val){
            return result;
        }else{
            //Otherwise, the next bit of the current operation node will call the delete method; After the processing result is linked to the current operation node;
            head.next=result;
            return head;
        }
    }

When debugging with debug, you notice that the method will be executed after entering the method;

Node result = removeAllValDg(head.next,val);

Thus, it enters the method again and again until the null at the end; Then compare with 12 from 14 upside down;

Then return to 13; At this time, 13 is the head node of the linked list; 14 is connected later, and 14 is null;

Execute in sequence; Until finally reaching 11;

Tags: data structure

Posted on Sat, 18 Sep 2021 10:31:30 -0400 by bouwob