Recurse in Linked List

后端 未结 2 347
栀梦
栀梦 2021-01-28 18:27

I have been practicing the linked list and wanted to implement the recurse on it, although in some cases I was able to implement it efficiently, in other cases I failed miserabl

2条回答
  •  遥遥无期
    2021-01-28 19:14

    This may or may not help. It suggests a substantially different way to build your lists.

    The idea is that recursion, although occasionally used with Object-Oriented (OO) systems, is much more closely tied to Functional Programming (FP). So if you're going to use recursion on your lists, you might as well use it with FP lists.

    Creating and manipulating lists is one of the strengths of FP, and we can write your code much more simply. We create a bare list of one item, 42 by calling const list1 = ins (42) (null). We prepend that with 17 by calling const list2 = ins (17) (list1). Or we can write a whole chain of these like this:

    const list3 = ins (1) (ins (2) (ins (3) (ins (4) (ins (5) (null)))))
    
    

    There are many differences from your code, but one of the most fundamental, is that this treats lists as immutable objects. None of our code will change a list, it will just create a new one with the altered properties.

    This is what ins might look like:

    const ins = (data) => (list) => 
      ({data, next: list})
    

    We could choose to write this as (data, list) => ... instead of (data) => (list) => .... That's just a matter of personal preference about style.

    But the basic construction is that a list is

    • a value
    • followed by either
      • another list
      • or null

    Here is an implementation of these ideas:

    const ins = (data) => (list) => 
      ({data, next: list})
    
    const del = (target) => ({data, next}) =>
      target == data ? next : next == null ? {data, next} : {data, next: del (target) (next)}  
    
    const delLast = ({data, next}) =>
      next == null ? null : {data, next: delLast (next)}
    
    const size = (list) => 
      list == null ? 0 : 1 + size (list.next)
    
    const search = (pred) => ({data, next}) => 
      pred (data) ? {data, next} : next != null ? search (pred) (next) : null
    
    const fnd = (target) => 
      search ((data) => data == target)
    
    const print = ({data, next}) => 
      data + (next == null ? '' : ('=>' + print (next)))    
    
    const list1 = ins (1) (ins (2) (ins (3) (ins (44) (ins (66) (null)))))
    const list2 = ins (33) (list1)
    const list3 = delLast (list2)
    
    console .log (fnd (3) (list3))
    console .log (size (list3))
    console .log (print (list3))
    console .log (list3)
    .as-console-wrapper {max-height: 100% !important; top: 0}

    Note that all of these functions, except for ins and find are directly recursive. They all call themselves. And find simply delegates the recursive work to search.

    It's too much to try to describe all of these functions, but lets look at two. print is a simple function.

    const print = ({data, next}) => 
      data + (next == null ? '' : ('=>' + print (next)))    
    

    We build our output string by including our data followed by one of two things:

    • an empty string, if next is null
    • '=>' plus the recursive print call on next, otherwise.

    del is a somewhat more complex function:

    const del = (target) => ({data, next}) =>
      target == data
        ? next 
        : next == null 
          ? {data, next: null} 
          : {data, next: del (target) (next)}  
    

    We test if our current data is the target we want to delete. If it is, we simply return the list stored as next.

    If not, we check whether next is null. If it is, we return (a copy of) the current list. If it is not, then we return a new list formed by our current data and a recursive call to delete the target from the list stored as next.


    If you want to learn more about these ideas, you probably want to search for "Cons lists" ("con" here is not the opposite of "pro", but has to do with "construct"ing something.)

    I used different terms than are most commonly used there, but the ideas are much the same. If you run across the terms car and cdr, they are equivalent to our data and next, respectively.

提交回复
热议问题