A quale livello di astrazione vengono creati i dati strutturati?

0

Sto imparando sulla lista e sulle matrici collegate nella mia classe di strutture dati. Li stiamo facendo in Java. Le strutture dati attuali sono progettate in Java / C? Oppure sono realizzati in linguaggi di livello inferiore come il montaggio? La lista collegata che abbiamo creato in classe sembra semplicemente semplice, mi fa pensare a come le strutture dati reali differiscano da ciò che mi viene insegnato.

Ecco uno snippet di codice da uno dei file:

import java.util.*;

/**
 * A class that implements our simple List interface using a linked list.
 * The linked list includes a dummy head node that allows us to avoid
 * special cases for insertion and deletion at the front of the list.
 */
public class LLList implements List {
    // Inner class for a node.  We use an inner class so that the LLList
    // methods can access the instance variables of the nodes.
    private class Node {
        private Object item;
        private Node next;

        private Node(Object i, Node n) {
            item = i;
            next = n;
        }
    }

    private Node head;     // dummy head node
    private int length;    // # of items in the list

    /**
     * Constructs a LLList object for a list that is initially empty.
     */
    public LLList() {
        head = new Node(null, null);
        length = 0;
    }

    /*
     * getNode - private helper method that returns a reference to the
     * ith node in the linked list.  It assumes that the value of the
     * parameter is valid.
     *
     * If i == -1, it returns a reference to the dummy head node.
     */
    private Node getNode(int i) {
        Node trav = head;
        int travIndex = -1;
        while (travIndex < i) {
            travIndex++;
            trav = trav.next;
        }
        return trav;
    }

    /** getItem - returns the item at position i in the list */
    public Object getItem(int i) {
        if (i < 0 || i >= length)
            throw new IndexOutOfBoundsException();
        Node n = getNode(i);
        return n.item;
    }

    /**
     * addItem - adds the specified item at position i in the list,
     * shifting the items that are currently in positions i, i+1, i+2,
     * etc. to the right by one.  Always returns true, because the list
     * is never full.
     *
     * We don't need a special case for insertion at the front of the
     * list (i == 0), because getNode(0 - 1) will return the dummy
     * head node, and the rest of insertion can proceed as usual.
     */
    public boolean addItem(Object item, int i) {
        if (i < 0 || i > length)
            throw new IndexOutOfBoundsException();

        Node newNode = new Node(item, null);
        Node prevNode = getNode(i - 1);
        newNode.next = prevNode.next;
        prevNode.next = newNode;

        length++;
        return true;
    }

    /**
     * removeItem - removes the item at position i in the list,
     * shifting the items that are currently in positions i+1, i+2,
     * etc. to the left by one.  Returns a reference to the removed
     * object.
     *
     * Here again, we don't need a special case for i == 0 (see the
     * note accompanying addItem above).
     */
    public Object removeItem(int i) {
        if (i < 0 || i >= length)
            throw new IndexOutOfBoundsException();

        Node prevNode = getNode(i - 1);
        Object removed = prevNode.next.item;
        prevNode.next = prevNode.next.next;

        length--;
        return removed;
    }

    /** length - returns the number of items in the list */
    public int length() {
        return length;
    }

    /**
     * isFull - always returns false, because the linked list can
     * grow indefinitely and thus the list is never full.
     */
    public boolean isFull() {
        return false;
    }

    /**
     * toString - converts the list into a String of the form
     * {item0, item1, ...}
     */
    public String toString() {
        String str = "{";

        Node trav = head.next;    // skip over the dummy head node
        while (trav != null) {
            str = str + trav.item;
            if (trav.next != null)
                str = str + ", ";
            trav = trav.next;
        }

        str = str + "}";
        return str;
    }

    /**
     * iterator - returns an iterator for this list
     */
    public ListIterator iterator() {
        return new LLListIterator();
    }

    /*
     *** private inner class for an iterator over an LLList ***
     */
    private class LLListIterator implements ListIterator {
        private Node nextNode;          // the next node to visit
        private Node lastVisitedNode;   // the most recently visited node

        public LLListIterator() {
            nextNode = head.next;
            lastVisitedNode = null;
        }

        /**
         * hasNext - does the iterator have additional items to visit?
         */
        public boolean hasNext() {
            return (nextNode != null);
        }

        /**
         * next - returns a reference to the next Object in the iteration
         */
        public Object next() {
            if (nextNode == null)
                throw new NoSuchElementException();

            Object item = nextNode.item;
            lastVisitedNode = nextNode;
            nextNode = nextNode.next;

            return item;
        }
    }
}
    
posta chopper draw lion4 12.10.2014 - 01:48
fonte

3 risposte

2

La risposta è entrambe. Le strutture dati sono implementate a tutti i livelli di astrazione per quanto riguarda le lingue. Per un linguaggio di livello relativamente alto come Java, in cui l'allocazione della memoria viene gestita automaticamente, è necessario definire la struttura dei dati in termini di classi e metodi Java.

In C, definirai le strutture (o gli array) e le funzioni che operano su di esse. Inoltre, poiché C non ha la gestione automatica della memoria, è necessario anche allocare lo spazio affinché le strutture di dati esistano e così via. Dovresti anche dire al compilatore quando deallocare quella memoria in modo da non esaurire la memoria (questo è un modo per ottenere perdite di memoria).

Java e C sono entrambi compilati rispettivamente con linguaggi di livello inferiore, bytecode JVM e linguaggio assembly. Ognuno di essi ha le proprie rappresentazioni di dati e operazioni ma sono più direttamente allineati con il modo in cui il computer viene eseguito dal programma sulle funzioni (nel caso di Java, si tratta di un computer virtuale ma il processo è simile). La gestione della memoria e così via sono specificate dal compilatore in base alle convenzioni stabilite dagli scrittori del compilatore, ma se si dovesse scrivere l'assembly / bytecode da soli, è possibile farlo, ma è necessario essere molto consapevoli di tutte le operazioni richieste per spostare i dati e operare su di esso oltre ad avere un buon modello mentale di come i vari registri e comandi di assemblaggio siano mappati sulla struttura che hai in mente.

Per quanto riguarda le strutture di dati reali in natura, sono spesso molto più sofisticate delle liste e degli array collegati. Spesso li usano come componenti ma esiste un'intera classe di strutture e grafici basati su alberi che non ne usano necessariamente uno, ma possono essere implementati con una struttura di base. Gli esempi includono heap , prova e alberi R.

Per quanto riguarda l'utilizzo, tuttavia, è molto più comune scegliere una struttura di dati preesistente da una libreria disponibile per una lingua piuttosto che una propria. Le ragioni di questo sono molte e varie ma le più comuni sono le prestazioni, la sicurezza e l'affidabilità. I progettisti di linguaggi di programmazione tendono ad essere persone molto istruite con una grande quantità di conoscenze su quali siano le migliori soluzioni possibili per rappresentare ciascuna struttura di dati e su come implementare tale rappresentazione in una determinata lingua.

Gli elenchi di Python, per esempio, usano Timsort piuttosto che Quicksort o Unisci Ordina perché in pratica è un ordinamento più veloce. Un altro buon esempio è quello delle strutture di dati sincronizzate e non sincronizzate in Java. Vectors sono deprecati a favore di ArrayList . Vectors fornisce un accesso sincronizzato a se stesso che spesso è problematico in un ambiente con multithreading (esattamente perché questo è il caso è meglio lasciarlo per un altro giorno). Esistono altri modi per implementare funzionalità simili, ma a costi inferiori in termini di tempo e spazio, quindi le persone tendono a utilizzarle ora.

Quindi, mentre rotolare le tue strutture dati è una cosa fantastica da fare per un esercizio di apprendimento, è qualcosa che generalmente eviti a meno che tu non abbia altra opzione dal momento che le strutture fornite nelle librerie delle tue lingue sono generalmente più testate e più brutalmente ottimizzato di qualsiasi cosa tu possa sperare di costruire da solo. Detto questo, è bello sapere come funzionano tutte queste cose in modo che tu possa analizzare correttamente il problema e scegliere le strutture appropriate per aiutarti a risolverlo, anche se utilizzi solo componenti fuori dallo scaffale.

    
risposta data 12.10.2014 - 02:24
fonte
3

Gli elenchi e gli array collegati sono molto semplici, ma sono anche strutture dati reali. Sono il modo più semplice per gestire un elenco di elementi, con elenchi collegati più semplici per elenchi di dimensioni che non conosciamo in anticipo e più semplici per elenchi di dimensioni (o dimensioni massime) che conosciamo.

Non è necessario immergersi in un linguaggio diverso, di livello inferiore (come l'assemblaggio) per creare strutture di dati.

The linked list we made in class just seems to simple

Nella programmazione, non esiste una cosa troppo semplice, a meno che non possa effettivamente fare ciò che ci serve per farlo. Come ha detto Einstein, "tutto dovrebbe essere reso il più semplice possibile, ma non più semplice".

Non pensare che solo perché una struttura dati utilizzata da un programma è semplice che il programma stesso è semplice - puoi fare cose molto complesse con strutture di dati molto semplici.

A volte le strutture di dati sono annidate l'una dentro l'altra per creare strutture di dati più complesse. Ad esempio, potresti avere un elenco collegato di matrici o una serie di elenchi collegati.

    
risposta data 12.10.2014 - 02:25
fonte
0

Direi che le strutture dati esistono almeno un livello di astrazione sotto il livello del linguaggio di programmazione, se non ovunque . Questo perché compilatori e interpreti creano strutture dati da qualsiasi codice sorgente tu le fornisca.

Se sei più interessato a sapere se uno di questi passaggi intermedi nascosti (compilatore, interprete, ecc.) utilizza strutture dati che riconoscerai , probabilmente anche la risposta è sì. Clojure implementa matrici come alberi "sotto il cofano" per esempio.

    
risposta data 12.10.2014 - 02:29
fonte

Leggi altre domande sui tag