1

I'm writing a Single Linked List that has the capability of sorting objects by a specific field as they are entered into the list. It's not adding everything, then sorting, but checking where it would be added before actually adding it. With this, I've developed a regex for three different types of sorted lists. My question is specifically about automatically sorting objects by a variable as they are added.

private void addDescending(E item)
{
     if(head == null)
     {
          head = new Node<E>(item, null);
          size++;
     }
     else
     {
          Node<E> p = head;
          while(p.next != null)
          {
               if(p.data.compareTo(item) > 0)
               {
                    Node<E> n = findPrev(p);
                    if(n == null)
                    {
                         Node<E> p1 = head;
                         head = new Node<E>(item, p1);
                         size++;
                         break;
                    }
                    n.next = new Node<E>(item, p);
                    size++;
                    break;
               }
          }
     }
}

public int compareTo(Object o)
{
     if(init == ((Person)(o)).getAge())
     {
          return 0;
     }
     else if(init > ((Person)(o)).getAge())
     {
          return 1;
     }
     else
     {
          return -1;
     }
}

The compareTo(Object o) method is within the Person class. findPrev(Node<E> currentNode) is similar to a node.previous in a Double Linked List. For my project, a Single Linked List is easier to implement.

The access is private within the class but there is a public add(E item). First, it checks to see if the head is null, creating one if it doesn't exist. If the head exists, it compares to the head. The compare code is in the Person class.

It checks the p.data that is checked as a Person to get its and compare it to the Person object that is being added's age. If it is larger, it goes before. If it is smaller, it goes after. If it is between, it goes before the larger number and before the smaller number. Meaning the head could be smaller than the number added, and as such the new head becomes the larger number with the old head becoming the next.

In my main, I'm adding four Person objects. They have the ages of 3, 10, 9, and 6 as tests. As the names are unimportant, they are simply Test1 through Test4. For some reason, it is only adding the first object. On a few occasions, I've had it add four objects, but four of the same object, even though all four are different. Why would it be adding only the same object repeatedly or only a single object?

Edit: I have just redone and updated the code. Here is the addDescending(E item) method now.

private boolean addDescending(E item)
{
    if(head == null)
    {
        head = new Node<E>(item, null);
        size++;
    }
    else
    {
        Node<E> p = head;       
        if(head.next == null && p.data.compareTo(item) > 0)
        {
            p.next = new Node<E>(item, null);
            head = p;
            size++;
            return true;
        }
        else if(head.next == null && p.data.compareTo(item) < 0)
        {
            head.next = new Node<E>(item, null);
            size++;
            return true;
        }

        while(p.next != null && p.data.compareTo(item) < 0)
        {                                       
            if(p.data.compareTo(item) > 0)
            {
                Node<E> n = findPrev(p);
                Node<E> p1 = p.next;
                p.next = new Node<E>(item, p1);
                size++;
                return true;
            }
        p = p.next;
        }
    }
    return false;
}

This code checks each node's object's age against the input age. If the current node object age is larger than the input, it goes to the next node until it finds one that is smaller than it. It then gets the previous and next nodes, creating a new node and placing itself between those two.

However, my inputs are still the four Person objects. I am adding the ages 3, 10, 9, and 6 in order.

The expected result is to initially create a head with a the object's age as 3. Then when adding 10, 10 is greater than 3, so it would be added before the head, becoming the new head. 6 would be added, check against 10, and because 10 is greater than 6, move to the next node. The next node, 3, is smaller than 6, so it would add itself right between 10 and 3. Similar with 9, but between 10 and 6.

The problem is one I'm not quite sure of. As I said, I have four inputs. I am getting two objects now, but they are both the same. The object with name = "Test1"; and age = 3;. I don't see any other objects but these two, and I can guarantee they are only entered once each.

Edit2: Here's the code that creates the Person objects, the regex for the list constructor, the get, the result of the get, and the output.

Constructor and Regex:

public LList(String regex) throws IllegalArgumentException
{
    size = 0;
    this.regex = regex;
    head = null;
    if(!(regex.equals("A") || regex.equals("D") || regex.equals("U")))
    {
        throw new IllegalArgumentException("Unexpected Regex");
    }
}

public void add(E item)
{
    if(regex.equals("D"))
    {
        addDescending(item);
    }
    else if(regex.equals("A"))
    {
        addAscending(item);
    }
    else if(regex.equals("U"))
    {
        addUnsorted(item);
    }
}

Get:

public E get(int index)
{
    int i = 0;
    Node<E> p = head;
    if(index == 0 && head != null)
    {
        return head.data;
    }
    else
    {
        while(p.next != null)
        {
            if(i == index)
            {
                return p.data;
            }
            p = p.next;
            i++;
        }
    }
    return null;
}

Main:

Person ch0 = new Person("Test1", 3);
Person ch1 = new Person("Test2", 10);
Person ch2 = new Person("Test3", 9);
Person ch3 = new Person("Test4", 6);

// Create Descending Order List
System.out.printf("Descending List%n%n");
System.out.printf("%-10s %-4s%n", "Name", "Age");
System.out.printf("%-10s %-4s%n", "----------", "---");

LList<Person> dList = new LList<Person>("D");
dList.add(ch0);
dList.add(ch1);
dList.add(ch2);
dList.add(ch3);


dList.get(0).print();
dList.get(1).print();
dList.get(2).print();
dList.get(3).print();

Person print method:

System.out.printf("%-10s %-4d%n", name, age);

Thanks for all the help!

Onefoot
  • 17
  • 6
  • One problem I saw on first glance is that in the case that the added item is greater than or equal to on the 'compareTo' condition, you never update p to p.next, so I don't see the loop exiting in that case. – Elenchus Feb 07 '19 at 00:52
  • Also, with ```head``` having a ```next``` of null, and the loop checking whether ```next``` is null, how will the loop ever add an entry past the head? – Elenchus Feb 07 '19 at 01:01
  • @Elenchus, I redid and updated code. Take a look for yourself. – Onefoot Feb 07 '19 at 01:43

1 Answers1

0

my 2 ct:

private boolean addDescending(E item){
    if(head == null){ //case new list
        head = new Node<E>(item, null);
        size++;
        return true;
    } else if(head.data.compareTo(item)>0){ // case insert befor head
        head = new Node<E>(item, head);
        size++;
        return true; 
    } else {
        Node<E> p; 
        for(p = head;p.next!=null; p=p.next){//compare all except head
           if(p.next.data.compareTo(item) > 0){
              p.next = new Node<E>(item, p.next);
              size++;
              return true;
           }
         }
         //not found: insert at the end
         p.next = new Node<E>(item, null);
         size++;
         return true;
     }
}
kai
  • 894
  • 1
  • 7
  • 15
  • This works almost perfectly. All four outputs are shown. For some reason though it's still giving me the same exact object for each output. I just checked the get and it's fine. I had it run in a for loop, but changed it to individual just to check, and it still gives the same exact objects. Not sure why though. – Onefoot Feb 07 '19 at 02:07
  • can you show the part that does calls the addDescending and the part that prints. – kai Feb 07 '19 at 02:11
  • I posted more code that includes creating the objects, initializing the list with regex, how the regex determines what add to use, the get method, and my main method. I also included the output. – Onefoot Feb 07 '19 at 02:32
  • and i found an error ;) "if(i == 0 && head != null)" is allways true – kai Feb 07 '19 at 02:39
  • Yep, that did it. It's always the little things like that. Thanks for all the help! – Onefoot Feb 07 '19 at 02:44