简体   繁体   中英

singly linked-list in java implementation

I have being given a task to implement the following method in Java: SubList(S, L) returns true if list S is a sublist of list L.

I need to use the following notation when I process lists as an abstract object in the recurrence relations. Given a list L, we write L = [H|R] where H is the head of the list and R is the rest of the list. For an empty list L, we write L = []. For example, if L = [1, 2, 3, 4, 5], H = 1, and R = [2, 3, 4, 5].

Hence my tasks are:

a) Provide the recurrence relations for SubList(S, L) using the above list notation.

b) Implement the recursive algorithm in Java using the recurrence relations.

Being stuck on this task for a day and a half now and still having trouble how to do this. Appreciate, if anyone can help me to solve this problem.

This is the java code I have been given to work with.

class SLLNode {

    public Object info;     // This is the data
    public SLLNode next;    // this is the address of the next node
    public SLLNode() {      // Here's how we construct an empty list.
        next = null;
    }
    public SLLNode(Object el) {
        info = el; next = null;
    }
    public SLLNode(Object el, SLLNode ptr) {
        info = el; next = ptr;
    }

}

class SLList {

    protected SLLNode head = null;
    public SLList() {
    }

    public void setToNull() {
        head = null;
    }

    public boolean isEmpty() {
        return head == null;
    }

    public Object first() {
        return head.info;
    }

    public SLLNode head() {
        return head;
    }

    public void printAll() {
       for (SLLNode tmp = head; tmp != null; tmp = tmp.next)
            System.out.print(tmp.info.toString());
    }

    public void add(Object el) {
        head= new SLLNode(el,head);
    }

    public Object find(Object el) {
        SLLNode tmp = head;
        for ( ; tmp != null && !el.equals(tmp.info); tmp = tmp.next);
        if (tmp == null)
             return null;
        else return tmp.info;
    }

    public boolean member(Object el) {
            SLLNode tmp = head;
            for ( ; tmp != null && !el.equals(tmp.info); tmp = tmp.next);
            if (tmp == null)
                 return false;
            else return true;
    }

    public Object deleteHead() { // remove the head and return its info;
        Object el = head.info;
        head = head.next;
        return el;
    }

    public void delete(Object el) {    // find and remove el;  
        if (head != null)              // if non-empty list;
             if (el.equals(head.info)) // if head needs to be removed;
                  head = head.next;
             else {
                  SLLNode pred = head, tmp = head.next;
                  for ( ; tmp != null && !(tmp.info.equals(el));
                          pred = pred.next, tmp = tmp.next);
                  if (tmp != null)     // if found
                        pred.next = tmp.next;
             }
    }

}
SubList([], L)      = true (1)
SubList(H|[], H|*)  = true (2)
SubList(H|[], [])   = false (3)
SubList(SH|[], H|R) = SubList(SH|[], H|[]) OR SubList(SH|[], R) (4)
SubList(SH|SR, L)   = SubList(SH|[], L) AND SubList(SR, L) (5)

In english, it means that if L contains the first element of your sublist S AND that it contains the remaining elements of the sublist, then your SubList method is gonna return true.

The recursion here visible on the 4th and 5th lines, where you see that we are invoking the same function again and again until SR contains only one element.

Ex:

L = [1,2,5]
S = [1,5]
SubList(S, L) = SubList([1,5], [1,2,5])
= SubList(1|[5], 1|[2,5]) (4+5)
= SubList(1|[], 1|[2,5]) AND SubList([5], 1|[2,5])
= SubList(1|[], 1|[2,5]) AND (SubList(5|[], 1|[]) OR SubList(5|[], [2,5]))
= SubList(1|[], 1|[2,5]) AND (SubList(5|[], 1|[]) OR (SubList(5|[], 2|[]) OR SubList(5|[], [5])))
= SubList(1|[], 1|[2,5]) AND (SubList(5|[], 1|[]) OR (SubList(5|[], 2|[]) OR SubList(5|[], 5|[])))
= true AND (false OR (false OR true))
= true AND true 
= true

Possible Java implementation:

public SLList(SLNode h) {
   this.head = h;
}

public SLList singletonList(SLNode n) {
    return new SLList(new SLNode(n.info));
}

public SLList remainingList(SLNode n) {
    if(n == null) return new SLList();
    return new SLList(n);
}

private static boolean subList(SLList s, SLList l) {
   if(s.isEmpty()) return true;
   if(l.isEmpty()) return false;
   if(s.head.next == null && l.first().equals(s.first())) return true;
   return (subList(singletonList(s.head), singletonList(l.head)) || 
     subList(singletonList(s.head), remainingList(l.head.next))) && 
     subList(remainingList(s.head.next), l);
}

I haven't tested the code, there might be some null checks missing but the important thing is that you get the idea of how recursion works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM