Implement and perform set operations on linked lists

4

Can anyone help me in implementing a threaded list to perform set operations? Without using native Java functions, such as ArrayList .

The algorithm already generates a linked list and adds new nodes, but how do I make an operation like union?

In Main , I'm instantiating two classes, each one would be a list with values, but what do I call a union function that takes these two lists as a parameter, and how do I cycle through them simultaneously? (I know how to go one at a time)

Code - Main

public class TrabalhoListas {

public static void main(String[] args) {
    ListaDinamica teste = new ListaDinamica();
    ListaDinamica teste2 = new ListaDinamica();
    teste.add(1);
    teste.add(2);
    teste.add(3);
    teste.imprimeLista();
    System.out.println("Segunda lista");
    teste2.add(1);
    teste2.add(6);
    teste2.add(3);
    teste2.imprimeLista();
    System.out.println("Primeira de novo");
    teste.imprimeLista();
}
}

--- List ---

public class Lista {

private int valor;
private Lista prox;

public Lista() {
}

public int getValor() {
    return valor;
}

public void setValor(int valor) {
    this.valor = valor;
}

public Lista getProx() {
    return prox;
}

public void setProx(Lista prox) {
    this.prox = prox;
}
}

Dynamic List

public class ListaDinamica {

Lista primeiro;
Lista ultimo;
int tamanho = 0;

public ListaDinamica() {
    primeiro = null;
    ultimo = primeiro;
}

public void add(int valor) {
    Lista novo = new Lista();
    novo.setValor(valor);
    tamanho++;
    if (primeiro == null) {
        primeiro = novo;
        ultimo = novo;
        novo.setProx(null);
    } else {
        novo.setProx(primeiro);
        primeiro = novo;
    }
}

public void imprimeLista() {
    Lista atual = primeiro;
    for(int i = 0; i < tamanho; i++){
        System.out.println(atual.getValor());
        atual = atual.getProx();
    }
}

public void uniao(){

}
}
    
asked by anonymous 28.03.2015 / 16:22

3 answers

0

I think this would be it, that simply modifies a ListaDinamica by concatenating another ListaDinamica on it:

public void uniao(ListaDinamica outraLista) {
    ultimo.setProx(outraLista.primeiro);
    ultimo = outraLista.ultimo;
    tamanho += outraLista.tamanho;
    removeDuplicatas();
}

And to remove duplicates, you end up going through the same list twice, one inside the other:

private void removeDuplicatas() {
    for (Lista a = primeiro; a != null; a = a.getProx()) {
        for (Lista b = a.getProx(); b != null; b = b.getProx()) {
            if (a.getValor() == b.getValor()) {
                a.setProx(b.getProx());
                tamanho--;
            }
        }
    }
}

This algorithm to remove duplicates is not very efficient (it has quadratic time complexity), but should work correctly and should serve its purposes. To make an efficient algorithm for this would be much more complicated, and in this case it would be better to use the classes that java already gives you (as HashSet or TreeSet ).

You should also place a call to removeDuplicatas() at the end of the add(int) method. Or create a search method and use it in the add(int) method to avoid adding an element that already exists.

And so, you use this method at the end of main method:

teste.uniao(teste2);
teste.imprimeLista();

If you prefer to join without modifying either list, it's best to follow the approach of my other answer .

    
28.03.2015 / 17:46
0

To merge two lists, simply go through the list 1 to the last "valid element" (! = null ) and add the list 2 as the next of this element.

public static void uniaoLista(Lista l1, Lista l2){

    //Lista auxiliar que vai percorrer a lista 1
    Lista lAux = l1;


    //Percorre a lista l1 até chegar ao ultimo "elemento válido", ou seja, != de null
    while(lAux.getProx()!=null){

        lAux = lAux.getProx();
    }

    //Quando este elemento é achado, dizemos que seu próximo elemento será a lista l2
    lAux.prox = l2;
}

In this way, you would not have to create a "Dynamic List" class, you would have to have a List object that receives the first list and then join this list to another one. Example:

Suppose the lists:

List l1 = 1-> 2- 4

List l2 = 5-> 6-> 7-> 8

To perform the join without ending list l1, once the objects are passed by reference, do:

...
Lista lUniao = l1.clone();
uniaoLista(lUniao,l2);

//lUniao = 1->2->3->4->5->6->7->8
    
28.03.2015 / 17:46
0

You can add a method to find out if an element exists in ListaDinamica :

public boolean existe(int elemento) {
    for (Lista a = primeiro; a != null; a = a.getProx()) {
        if (a.getValor() == elemento) return true;
    }
    return false;
}

Modify method add(int) to not allow duplicates to be added:

public void add(int valor) {
    if (existe(valor)) return; // Não deixa adicionar duplicatas.
    Lista novo = new Lista();
    novo.setValor(valor);
    tamanho++;
    if (primeiro == null) {
        primeiro = novo;
        ultimo = novo;
        novo.setProx(null);
    } else {
        novo.setProx(primeiro);
        primeiro = novo;
    }
}

And in the union, just add all the elements of the other list:

public void uniao(ListaDinamica outraLista) {
    for (Lista a = outraLista.primeiro; a != null; a = a.getProx()) {
        add(a.getValor());
    }
}

And so, you use this method at the end of main method:

teste.uniao(teste2);
teste.imprimeLista();

You may not like the fact that uniao modifies the list. If this is the case, and you really want to create a new list without modifying any of the two, then do this:

public ListaDinamica uniao(ListaDinamica outraLista) {
    ListaDinamica novaLista = new ListaDinamica();
    for (Lista a = primeiro; a != null; a = a.getProx()) {
        novaLista.add(a.getValor());
    }
    for (Lista a = outraLista.primeiro; a != null; a = a.getProx()) {
        novaLista.add(a.getValor());
    }
    return novaLista;
}

And then in your method main :

ListaDinamica teste3 = teste.uniao(teste2);
teste3.imprimeLista();
    
28.03.2015 / 18:10