Responsabili:
În urma parcurgerii acestui laborator studentul va fi capabil:
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:
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ă.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)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.
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).
Fiecare nod din listă liniara dublu înlănţuită are două legături:
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.
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
1) [5p] Implementați în header-ul definit anterior funcțiile pentru o listă liniară dublu înlănțuită.
2) [2p] Implementați o stivă folosind liste.
#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.
#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.
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ă.