List that contains only the elements of the one of the two given lists

  • Context: MHB 
  • Thread starter Thread starter evinda
  • Start date Start date
  • Tags Tags
    Elements List
Click For Summary

Discussion Overview

The discussion revolves around creating an algorithm to generate a new list, $M_3$, that contains elements from a sorted list $M_1$ that do not exist in another sorted list $M_2$. The focus is on algorithm design, efficiency, and correctness, with participants exploring various approaches and addressing potential errors in the proposed solutions.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Mathematical reasoning

Main Points Raised

  • One participant proposes an initial algorithm but is uncertain about its correctness and efficiency.
  • Another participant points out that the initial algorithm does not properly create a new list and fails to utilize the sorted nature of the lists.
  • A later reply expresses concern about whether the algorithm is entirely wrong and seeks clarification on how to create a new list.
  • Participants discuss the possibility of achieving a time complexity of $O(n+m)$, where $n$ and $m$ are the sizes of the lists, emphasizing the importance of leveraging the sorted property of the lists.
  • One participant shares a revised algorithm but acknowledges that it results in a time complexity of $O(n \cdot m)$ instead of the desired $O(n+m)$, seeking suggestions for improvement.
  • Another participant critiques the revised algorithm, highlighting specific coding errors and suggesting that the order of conditions in the while loop needs adjustment for proper execution.
  • Further discussion includes a proposed pseudocode revision, but participants remain uncertain about the correctness of the approach.

Areas of Agreement / Disagreement

Participants express disagreement regarding the correctness of the initial algorithm and the subsequent revisions. There is no consensus on a final solution, and multiple competing views on how to approach the problem remain present throughout the discussion.

Contextual Notes

Participants note limitations in the proposed algorithms, including issues with list creation, condition evaluation, and accessing the resulting list. The discussion highlights the need for careful consideration of edge cases and the importance of testing algorithms with sorted lists.

evinda
Gold Member
MHB
Messages
3,741
Reaction score
0
Hi! (Smile)

Given two sorted lists $M_1, M_2$, I want to write an algorithm, that creates a new list $M_3$, that contains the elements of $M_1$, that do not exist in $M_2$.

That's what I have tried:

Code:
Algorithm(M1,M2){
    pointer q=M1, p=M2, M3;
    int same=0;
    if (M1==NULL) return error;
    else if (M2==NULL) return M1;

    while (q!=NULL){
            while (p!=NULL){
                    if (p->data==q->data){
                       same=1;
                    }
                    p=p->next;
            }
            if (same==0){
                M3=q;
                M3=M3->next;
            }
            q=q->next;
    }   
    return M3;

Could you tell me if it is right or if I have done something wrong? (Thinking)
Is there also a better way to do this? :confused:
 
Technology news on Phys.org
This is wrong. First, you never create a new list M3; you only assign to M3 some tail of (tail of tail of...) M1. Second, you never use comparison and therefore ignore the fact that the lists are sorted.

P.S. Don't put a comma before "that". See http://www.grammarly.com/handbook/punctuation/comma/28/comma-setting-off-restrictive-clauses/.
 
Evgeny.Makarov said:
This is wrong.
So, is it totally wrong? (Worried)

Evgeny.Makarov said:
First, you never create a new list M3; you only assign to M3 some tail of (tail of tail of...) M1. Second, you never use comparison and therefore ignore the fact that the lists are sorted.

How can we create then a new list? (Thinking)

Is it possible that we write an algorithm with time complexity $O(n+m)$, where $n$ is the number of elements of $M_1$ and $m$ is the number of elements of $M_2$?
Evgeny.Makarov said:
P.S. Don't put a comma before "that". See http://www.grammarly.com/handbook/punctuation/comma/28/comma-setting-off-restrictive-clauses/.

Ok... (Nod)
 
evinda said:
So, is it totally wrong?
I am afraid so.

evinda said:
How can we create then a new list?
For this you need to create a new record with fields [m]data[/m] and [m]next[/m]. I have not been following your other threads, so I am not sure how this is done in your programming language.

evinda said:
Is it possible that we write an algorithm with time complexity $O(n+m)$, where $n$ is the number of elements of $M_1$ and $m$ is the number of elements of $M_2$?
That's the idea. To do this, you need to use the fact that the lists are sorted.

I recommend considering several example lists and figuring out how the algorithm should work in those examples. Then formulate the general algorithm.
 
I tried this:
Code:
Algorithm(M1,M2){
  pointer p=M1, q=NULL, M3=NULL;
  while (p!=NULL){
           q=M2;
           while (q->data<p->data and q!=NULL){
                    q=q->next;
            }
            if (q->data!=p->data){
               if (M3==NULL) M3->data=p->data;
               else{
                      M3= M3->next
                      M3->data=p->data;
               }
            }
            p=p->next;
   }
}
But now the time complexity is $O(n \cdot m)$ instead of $O(n+m)$, right?
What could I change? (Thinking)
 
Evinda,
I'm afraid you're doomed to continue making errors until you're willing to let the computer help you by implementing your ideas with a real programming language.

1. while (q->data < p->data and q != null): If q is null, this won't work in any programming language that I know. If the language has "shortcut" evaluation (C++ or Java), you need to change the order of the conditions.

2. if (M3 == null) M3->data=p->data:
This fails period.

3. M3=M3->next;
M3->data=p->data; :
Even if somehow this would make sense, at the end of your algorithm, you have no way of accessing the created difference.

Following is a complete solution in C++. Notice to test the solution, you need to have sorted lists. The testing of all possible situations is an art; I think you ought to become familiar with this testing problem.

Code:
#include <cstdlib>
#include <cstddef>
#include <iostream>
#include <cmath>
#include <iomanip>

using namespace std;

/* class Node is as specified.  The linked lists are singly linked with no
 * header node.
 */

class Node {
public:
  int data;
  Node* next;
  Node():data(0),next(0){};
  Node(int x):data(x),next(0){};
};

/*  Makes a sorted linked list of nodes with "random" data fields.  This list
 * represents a multiset; i.e. not all data fields need be different.  The list
 * is created (for n != 0) by first creating a node with random data and then 
 * inserting a new node with random data into its proper position.
 */
Node* makeSortedList(int n) {
  if (n == 0) {
    return(NULL);
  }
  Node *first, *p, *q, *r;
  int x = rand() % 100, i;
  first = new Node(x);
  for (i = 1; i < n; i++) {
    x = rand() % 100;
    r = new Node(x);
    q = NULL;
    p = first;
    while (p != NULL && p->data < x) {
      q = p;
      p = p->next;
    }
    if (q == NULL) {
      r->next = first;
      first = r;
    } else {
      r->next = q->next;
      q->next = r;
    }
  }
  return (first);
}

/*  Just displays a list for debugging purposes.
 */
void printList(Node* first) {
  cout << "{";
  while (first != NULL) {
    cout << first->data << ", ";
    first = first->next;
  }
  cout << "}" << endl;
}

/* Upon entry A and B point to sorted "multiset" lists of size m and n, 
 * respectively.  This computes and returns a new list, the "multiset"
 *  difference A - B. The algorithm is "obviously" of order  m + n.
 */
Node* AminusB(Node* A, Node* B) {
  Node *first, *p = A, *q, *pB = B;
  first = NULL;
  if (A == NULL) {
    return (first);
  }
  while (pB != NULL) {
    while (p != NULL && p->data < pB->data) {
      if (first == NULL) {
        first = new Node(p->data);
        q = first;
      } else {
        q->next = new Node(p->data);
        q = q->next;
      }
      p = p->next;
    }
    if (p == NULL) {
      return (first);
    }
    if (p->data == pB->data) {
      p = p->next;
    }
    pB = pB->next;
  }
  if (first == NULL) {
    first = new Node(p->data);
    q = first;
    p = p->next;
  }
  while (p != NULL) {
    q->next = new Node(p->data);
    q = q->next;
    p = p->next;
  }
  return (first);
}

int main(int argc, char** argv) {
  Node *M1, *M2, *M3;
  M1 = makeSortedList(10);
  printList(M1);
  M2 = makeSortedList(15);
  printList(M2);
  M3 = AminusB(M1, M2);
  printList(M3);
  return 0;
}
 
johng said:
1. while (q->data < p->data and q != null): If q is null, this won't work in any programming language that I know. If the language has "shortcut" evaluation (C++ or Java), you need to change the order of the conditions.

So we could also just change the order of the conditions at a pseudocode, or not?

johng said:
3. M3=M3->next;
M3->data=p->data; :
Even if somehow this would make sense, at the end of your algorithm, you have no way of accessing the created difference.
So should the algorithm look like that?

Code:
Algorithm(M1,M2){
  pointer p=M1, q=NULL, M3=NULL, k=NULL;
  while (p!=NULL){
           q=M2;
           while (q->data<p->data and q!=NULL){
                    q=q->next;
            }
            if (q->data!=p->data){
               if (k==NULL) k->data=p->data;
               else{
                      k= k->next;
                      k->data=p->data;
               }
            }
            p=p->next;
   }
   M3=k;
   return M3;
}

johng said:
Following is a complete solution in C++. Notice to test the solution, you need to have sorted lists. The testing of all possible situations is an art; I think you ought to become familiar with this testing problem.

Code:
#include <cstdlib>
#include <cstddef>
#include <iostream>
#include <cmath>
#include <iomanip>

using namespace std;

/* class Node is as specified.  The linked lists are singly linked with no
 * header node.
 */

class Node {
public:
  int data;
  Node* next;
  Node():data(0),next(0){};
  Node(int x):data(x),next(0){};
};

/*  Makes a sorted linked list of nodes with "random" data fields.  This list
 * represents a multiset; i.e. not all data fields need be different.  The list
 * is created (for n != 0) by first creating a node with random data and then 
 * inserting a new node with random data into its proper position.
 */
Node* makeSortedList(int n) {
  if (n == 0) {
    return(NULL);
  }
  Node *first, *p, *q, *r;
  int x = rand() % 100, i;
  first = new Node(x);
  for (i = 1; i < n; i++) {
    x = rand() % 100;
    r = new Node(x);
    q = NULL;
    p = first;
    while (p != NULL && p->data < x) {
      q = p;
      p = p->next;
    }
    if (q == NULL) {
      r->next = first;
      first = r;
    } else {
      r->next = q->next;
      q->next = r;
    }
  }
  return (first);
}

/*  Just displays a list for debugging purposes.
 */
void printList(Node* first) {
  cout << "{";
  while (first != NULL) {
    cout << first->data << ", ";
    first = first->next;
  }
  cout << "}" << endl;
}

/* Upon entry A and B point to sorted "multiset" lists of size m and n, 
 * respectively.  This computes and returns a new list, the "multiset"
 *  difference A - B. The algorithm is "obviously" of order  m + n.
 */
Node* AminusB(Node* A, Node* B) {
  Node *first, *p = A, *q, *pB = B;
  first = NULL;
  if (A == NULL) {
    return (first);
  }
  while (pB != NULL) {
    while (p != NULL && p->data < pB->data) {
      if (first == NULL) {
        first = new Node(p->data);
        q = first;
      } else {
        q->next = new Node(p->data);
        q = q->next;
      }
      p = p->next;
    }
    if (p == NULL) {
      return (first);
    }
    if (p->data == pB->data) {
      p = p->next;
    }
    pB = pB->next;
  }
  if (first == NULL) {
    first = new Node(p->data);
    q = first;
    p = p->next;
  }
  while (p != NULL) {
    q->next = new Node(p->data);
    q = q->next;
    p = p->next;
  }
  return (first);
}

int main(int argc, char** argv) {
  Node *M1, *M2, *M3;
  M1 = makeSortedList(10);
  printList(M1);
  M2 = makeSortedList(15);
  printList(M2);
  M3 = AminusB(M1, M2);
  printList(M3);
  return 0;
}

I will take a look at it..
 

Similar threads

  • · Replies 25 ·
Replies
25
Views
3K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 7 ·
Replies
7
Views
2K
  • · Replies 7 ·
Replies
7
Views
3K
Replies
9
Views
3K
  • · Replies 8 ·
Replies
8
Views
2K
  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 9 ·
Replies
9
Views
3K
  • · Replies 29 ·
Replies
29
Views
4K