QuickSort

Ola!

Bom pessoal, estou com uma dúvida de como usar o método quicksort para uma lista duplamente encadeada.

Preciso de um método que faça mais ou menos isso:

Este, recebe uma Lista Duplamente Encadeada (no caso DLinkedList), e utilizando o método QuickSort, ele ordena esta lista.

Eu já vi o método quicksort, porém ele faz isto apenas com vetores normais.

Eu tinha uma ideia de fazer este método da seguinte forma:
Ps.: este método fica dentro da classe DLinkedList

[code]public DLinkedList ordenaDLinkedList(DLinkedList dll){
int sizedll = (int) dll.size; //número de nós da lista
DNode current = head; //auxiliar para percorrer a lista duplamente encadeada
E[] vetor = new E[sizedll]; //esta linha não compila, diz o seguinte “Cannot created generic array of E”
for(int i = 0;i<vetor.length;i++ , current = current.getNext()){ //este for pegaria cada elemento da lista e adicionaria em uma posição do array
vetor[i] = current.getElement(); //atribui nó ao indice i do vetor
}
QuickSort.sort(dll); //chamando o método quicksort ele ordenaria o array
current = tail; // auxiliar que neste caso fica sendo o último nó da lista duplamente encadeada
DLinkedList ordenada = new DLinkedList(); //lista que ficara ordenada
for(int i = vetor.length;i>0;i–,current=current.getPrevious()){ //atribui os valores do vetor ordenado para a nova lista
ordenada.addFirst(vetor[i]);
}
return ordenada; //retorna a lista

}[/code]

Porém este método não funciona, devido ao erro da linha 4.

Alguém têm sugestões de como eu póssa fazer?

Grato por enquanto…

Segue as classes da Lista Duplamente Encadeada e o restante que é necessário para ela.

[code]public class DLinkedList {
protected DNode head; //nodo cabeça da lista
protected DNode tail; //nodo cauda da lista
protected long size; //número de nodos da lista

public DLinkedList() {
	size = 0;
	head = tail = null;
}

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

public E getFirst() throws UnderflowException {
	if (isEmpty())
		throw new UnderflowException();
	return head.getElement();
}

public E getLast() throws UnderflowException {
	if (isEmpty())
		throw new UnderflowException();
	return tail.getElement();
}

public void addFirst(E insertItem) {
	DNode<E> n = new DNode<E>(insertItem);
	if (isEmpty()) {
		head = tail = n;
	} else {
		head.setPrevious(n);
		n.setNext(head);
		head = n;
	}
	size++;
}

public void addLast(E insertItem) {
	DNode<E> n = new DNode<E>(insertItem);
	if (isEmpty()) {
		head = tail = n;
	} else {
		tail.setNext(n);
		n.setPrevious(tail);
		tail = n;
	}
	size++;
}

public E removeFirst() throws UnderflowException {
	if (isEmpty()) {
		throw new UnderflowException();
	}
	E removedItem = head.getElement();
	if (head == tail) {
		head = tail = null;
	} else {
		head = head.getNext();
		head.setPrevious(null);
	}
	size--;
	return removedItem;
}

public E removeLast() throws UnderflowException {
	if (isEmpty()) {
		throw new UnderflowException();
	}
	E removedItem = tail.getElement();
	if (head == tail) {
		head = tail = null;
	} else {
		DNode<E> penultimo = tail.getPrevious();
		tail = penultimo;
		tail.setNext(null);
	}
	size--;
	return removedItem;
}

public void print() {
	System.out.println("Exibindo a lista:");
	DNode<E> current = head;
	while (current != null) {
		System.out.println(current.getElement());
		current = current.getNext();
	}
}

public DNode<E> find(E key) {
	DNode<E> current = head;
	while (current != null) {
		if (current.getElement().equals(key)) {
			return current;
		}
		current = current.getNext();
	}
	return null;
}

public boolean addBefore(E el, E chave) {
	DNode<E> current = find(chave);
	if (current == null) {
		return false;
	} else if (current == head) {
		addFirst(el);
		return true;
	} else {
		DNode<E> n2 = new DNode<E>(el);
		DNode<E> before = current.getPrevious();
		before.setNext(n2);
		n2.setPrevious(before);
		n2.setNext(current);
		current.setPrevious(n2);
		return true;
	}
}


public static void main(String args[]) {
	DLinkedList<Integer> list = new DLinkedList<Integer>();
	list.addLast(2);
	list.addLast(4);
	list.addLast(6);
	list.addLast(1);
	list.addLast(8);
	list.addLast(9);
	list.print();
	/*try {
		list.removeFirst();
	} catch (UnderflowException e) {
		e.printStackTrace();
	}
	list.print();*/
	System.out.println(list.find(1));
	System.out.println(list.addBefore(5, 6));
	list.print();
}

} // end class List
[/code][code]public class DNode {
private E element;
private DNode next;
private DNode previous;

public DNode(E element) {
	this (element, null, null);
}
public DNode(E element, DNode<E> next, DNode<E> previous) {
	super();
	this.element = element;
	this.next = next;
	this.previous = previous;
}
public E getElement() {
	return element;
}
public void setElement(E element) {
	this.element = element;
}
public DNode<E> getNext() {
	return next;
}
public void setNext(DNode<E> next) {
	this.next = next;
}
public DNode<E> getPrevious() {
	return previous;
}
public void setPrevious(DNode<E> previous) {
	this.previous = previous;
}

public String toString() {
	return "DNode [element=" + element + "]";
}

}
[/code]public class UnderflowException extends Exception { public String toString() { return "UNDERFLOW!"; } }

esse ‘E’ é o tipo ou objeto ? se for tipo vai dar erro mesmo. pq se num substitui por :

Object[] vetor = new Object[sizedll];

[quote=kdoigor]esse ‘E’ é o tipo ou objeto ? se for tipo vai dar erro mesmo. pq se num substitui por :

Object[] vetor = new Object[sizedll]; [/quote]

Vou tentar.

E é pra ser o tipo. Tendo em vista que ele recebe também uma lista de “E”.

Depois posto o resultado.

Não funcionou, pois o método QuickSort não aceita um Object[].

Tem que ser um E[] mesmo.

Já estou quase desistindo disso. :frowning:

Tem outra sugestão?

Segue o QuickSort, caso queira dar uma olhada…

[code]import java.util.Arrays;
import java.util.Random;

public class QuickSort {
public static final Random RND = new Random();

private static void swap(Object[] array, int i, int j) {
    Object tmp = array[i];
    array[i] = array[j];
    array[j] = tmp;
}

private static <E extends Comparable<? super E>> int partition(E[] array, int begin, int end) {
    int index = begin + RND.nextInt(end - begin + 1);
    E pivot = array[index];
    swap(array, index, end);
    for (int i = index = begin; i < end; ++i) {
        if (array[i].compareTo(pivot) <= 0) {
            swap(array, index++, i);
        }
    }
    swap(array, index, end);
    return (index);
}

private static <E extends Comparable<? super E>> void qsort(E[] array, int begin, int end) {
    if (end > begin) {
        int index = partition(array, begin, end);
        qsort(array, begin, index - 1);
        qsort(array, index + 1, end);
    }
}

public static <E extends Comparable<? super E>> void sort(E[] array) {
    qsort(array, 0, array.length - 1);
}

// Exemplo de uso
public static void main(String[] args) {

    // Ordenando Inteiros
    Integer[] l1 = { 5, 1024, 1, 88, 0, 1024 };
    System.out.println("l1  start:" + Arrays.toString(l1));
    QuickSort.sort(l1);
    System.out.println("l1 sorted:" + Arrays.toString(l1));

    // Ordenando Strings
    String[] l2 = { "gamma", "beta", "alpha", "zoolander" };
    System.out.println("l2  start:" + Arrays.toString(l2));
    QuickSort.sort(l2);
    System.out.println("l2 sorted:" + Arrays.toString(l2));
}

}[/code]

Cara!!

Esse mundos dos generics é muito doido.

E nessa área dos arrays parece que nada funciona fácil e como um todo.

Fiz umas mudanças no teu código, mas tudo acaba não dando certo por causa dos Bounds (dos limites).

O QuickSort quer uma coisa e você só pode fornecer outra.

Ao invés do teu E[] que obviamente é impossível, tentei um

java.util.List<E> vetor = new java.util.ArrayList <E>();

O meu maior problema aqui é que que ArrayList não aceita Bounds, se aceitasse, bastava colocar o <? super E> e
tudo estaria resolvido.

Bem, daí é claro que mudei o teu for para poder colocar os Elementos no array:

for(int i = 0;i<sizedll;i++ , current = current.getNext()){ 
      vetor.add(current.getElement()); //atribui nó ao indice i do vetor   
} 

sem problemas

e daí mudei a classe QuickSort (que estranhamente aceita parâmetros (E[] que não podem ser construídos . kkkkkk)

por métodos parecidos que aceitem ArrayList


public static <E extends Comparable<? super E>> void sort(java.util.ArrayList<E> array) {
        qsort(array, 0, array.size() - 1);
    }
    
    private static <E extends Comparable<? super E>> void qsort(java.util.ArrayList<E> array, int begin, int end) {
        if (end > begin) {
            int index = partition(array, begin, end);
            qsort(array, begin, index - 1);
            qsort(array, index + 1, end);
        }
    }
    
    private static <E extends Comparable<? super E>> int partition(java.util.ArrayList<E> array, int begin, int end) {
        int index = begin + RND.nextInt(end - begin + 1);
        E pivot = array.get(index);
        swap(array, index, end);
        for (int i = index = begin; i < end; ++i) {
            E tmp = array.get(i);
            if (tmp.compareTo(pivot) <= 0) {
                swap(array, index++, i);
            }
        }
        swap(array, index, end);
        return (index);
    }
    
    private static <E extends Comparable<? super E>> void swap(java.util.ArrayList<E> array, int i, int j) {
        E tmp = array.get(i);
        array.remove(i);
        array.add(i, array.get(j));
        array.remove(j);
        array.add(j, tmp);
    }

e então tentei (sem sucesso) achar um jeito de fazer o QuickSort.sort(aceitar meu vetor).

public DLinkedList<E> ordenaDLinkedList(DLinkedList<E> dll){   
        int sizedll = (int) dll.size; //número de nós da lista   
        DNode<E> current = head; //auxiliar para percorrer a lista duplamente encadeada 
        java.util.List<E> vetor = new java.util.ArrayList <E>();
        //E[] vetor = new E[sizedll]; //esta linha não compila, diz o seguinte "Cannot created generic array of E"
        for(int i = 0;i<sizedll;i++ , current = current.getNext()){ //este for pegaria cada elemento da lista e adicionaria em uma posição do array   
            vetor.add(current.getElement()); //atribui nó ao indice i do vetor   
        }   
        QuickSort.sort(vetor); //chamando o método quicksort ele ordenaria o array
        
        current = tail; // auxiliar que neste caso fica sendo o último nó da lista duplamente encadeada   
        DLinkedList<E> ordenada = new DLinkedList<E>(); //lista que ficara ordenada   
        for (int i = vetor.size(); i > 0; i--, current = current.getPrevious()) {  //atribui os valores do vetor ordenado para a nova lista 
            E temp = vetor.get(i);
            ordenada.addFirst(temp);
        }
        return ordenada; //retorna a lista                         
    }  

Mas não deu, parece que tudo se resume aos limites na chamada do sort.

To mandando só por que de alguma maneira isso possa te dar alguma idéia.

Malditos generics…

Abandonei isso, já quebrei a cabeça d+.

Desisto.