Laborator 06 - Liste generice

Obiective

În urma parcurgerii acestui laborator studentul va fi capabil:

  • să înţeleagă structura tipului de date listă.
  • să descrie şi să folosească diversele implementări ale TAD listă.
  • să folosească în aplicaţii structura de date listă (să descrie soluţia unor aplicaţii ce folosesc liste pentru modelarea datelor utilizate).
  • sa implementeze structurile studiate folosind liste.

Liste

O listă este o instanţă a unui tip de date abstract ce formalizează conceptul de colecţie ordonată de entităţi. În mod minimal, o listă este caracterizată prin:

  • Operaţii
    • Add - adaugă un element (entitate) la listă. Adăugarea se poate face la începutul listei, sfârşitul listei, sau într-o poziţie arbitrară.
    • Remove - şterge un element din listă. Identificarea elementului ce urmează a fi eliminat se poate face pe baza poziţiei sale (iterator), sau a conţinutului. De asemenea ştergerea se poate face de la începutul sau de la sfîrşitul listei.
    • Get - consultă un element din listă. Identificarea elementului se face prin poziţie.
    • Update - actualizează informaţia conţinută de un element din listă.
  • Proprietăţi:
    • lungimea - numărul de elemente din listă. De cele mai multe ori, se implementează într-o funcţie de tipul GetSize()
    • tipul - felul elementelor din listă. Întâlnită mai ales în implementările din limbaje care suportă tipuri generice (C++, Java, .NET)

Cum se implementează?

Pentru implementarea listelor, există două modalităţi de bază: folosind liste înlănţuite (simplu sau dublu înlănţuite) sau folosind array-uri dinamice.

Tipuri de liste înlănţuite

Listă liniară simplu înlănţuită

Are o singură legatură la fiecare nod. Această legatură indică întotdeauna următorul nod din listă, sau o valoare nulă (dacă suntem la finalul listei), sau o listă liberă (pentru identificarea ei).

Listă liniară dublu-înlănţuită

Fiecare nod din listă liniara dublu înlănţuită are două legături:

  • una leagă nodul actual de nodul de dinaintea lui, sau leagă nodul actual cu o listă libera, sau cu o listă care are o valoare nulă dacă aceasta este la începutul primului nod.
  • cealaltă legatură leagă nodul actual de o listă care are o valoare nulă sau cu o listă liberă dacă această reprezintă nodul final.

Listă circulară simplu-înlănţuită

Primul şi ultimul nod sunt legate împreună. Pentru a parcurge o listă circular înlănţuită se începe de la oricare nod şi se urmăreşte lista prin aceasta direcţie aleasă până când se ajunge la nodul de unde s-a pornit parcurgerea (lucru valabil şi pentru listele circulare dublu-înlănţuite).

Fiecare nod are o singură legatură, similar cu listele liniare simplu-înlănţuite, însă, diferenţa constă în legătura aflată după ultimul nod ce îl leagă pe acesta de primul nod. La fel ca şi în listele liniare simplu-înlănţuite, nodurile noi pot fi inserate eficient numai dacă acestea se află după un nod care are referinţe la acesta. Din acest motiv, este necesar să se menţină numai o referinţă către ultimul element dintr-o listă circulară simplu-înlănţuita, căci aceasta permite o inserţie rapidă la nodul de început al listei, şi de asemenea, permite accesul la primul nod prin legatura dintre acesta şi ultimul nod.

Listă circulară dublu înlănţuită

list.h
template <typename T>
struct Node {
    T value;
    Node<T> *next, *prev;
    Node (T value) {
	this->value = value;
        next = prev = NULL;
    }
    Node() {
        next = prev = NULL; 
    }
};
 
template <typename T>
class LinkedList {
private:
    Node<T> *pFirst, *pLast;
public: 
    // Constructor
    LinkedList();
    // Destructor
    ~LinkedList();
 
    /* Adauga un nod cu valoarea == value la inceputul listei. */
    void addFirst(T value);
 
    /* Adauga un nod cu valoarea == value la sfarsitul listei. */
    void addLast(T value);
 
    /* Elimina elementul de la inceputul listei si intoarce valoarea acestuia. */
    T removeFirst();
 
    /* Elimina elementul de la sfarsitul listei listei si intoarce valoarea acestuia. */
    T removeLast();
 
    /* Elimina prima aparitie a elementului care are valoarea == value. */
    T removeFirstOccurrence(T value);
 
    /* Elimina ultima aparitie a elementului care are valoarea == value. */
    T removeLastOccurrence(T value);
 
    /* Afiseaza elementele listei pe o singura linie, separate printr-un spatiu. */
    void printList();
 
    /* Intoarce true daca lista este vida, false altfel. */
    bool isEmpty();
};
 
#endif

Exerciții

1) [5p] Implementați în header-ul definit anterior funcțiile pentru o listă liniară dublu înlănțuită.

  • [3p] constructor, destructor(eliberați memoria folosită) și isEmpty.
  • [1p] addFirst și addLast.
  • [1p] removeFirst, removeLast si removeFirstOccurence.

2) [2p] Implementați o stivă folosind liste.

stack.h
#ifndef __STACK__H
#define __STACK__H
 
template<typename T>
class Stack {
public:
    // Constructor
    Stack();
 
    // Destructor
    ~Stack();
 
    void push(T x);
    T pop();
    T peek();
    int isEmpty();
 
private:
    // Vectorul de stocare.
    LinkedList<T> stackList;
    // De ce nu mai este nevoie sa retinem topLevel?
};
#endif

3) [2p] Implementați o coadă folosind liste.

queue.h
#ifndef __QUEUE_H
#define __QUEUE_H
 
template <typename T>
class Queue {
private:
    // De ce nu mai este nevoie sa retinem head, tail si size?
    LinkedList<T> queueList;
 
public:
    // Constructor.
    Queue();
 
    // Destructor.
    ~Queue();
 
    void enqueue(T e);
    T dequeue();
    T front();
    int isEmpty();
};
 
#endif

BONUS [bragging rights] Implementati inversarea unei liste simplu inlantuite, fara memorie auxiliara.

Interviu

Această secțiune nu este punctată și încearcă să vă facă o oarecare idee a tipurilor de întrebări pe care le puteți întâlni la un job interview (internship, part-time, full-time, etc.) din materia prezentată în cadrul laboratorului.

1. Scrieti un program care sa afizeseze elementul din mijlocul unei liste fara a folosi un contor si fara a sti dimensiunea listei.

2. Scrieti un program care se detecteze o bucla intr-o lista simplu inlantuita.

3. Scrieți o funcție care inversează o listă simplu înlănțuită fără a folosi memorie auxiliară.

Resurse

sd-ca/2015/laboratoare/laborator-06.txt · Last modified: 2017/02/18 11:12 by dragos.dimitriu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0