Note de curs, probleme algoritmică, clasa IX/X, 16 ianuarie 2015

From Algopedia
Jump to navigationJump to search

În acest curs am implementat operațiile clasice pe trei dintre structurile de date elementare: stiva, coada și heap-ul folosind paradigma programării funcționale.

Stiva

Să se implementeze o stivă, cu operațiile emptyStack, isEmpty, push, peek, pop și reverse.

#include <cstdio>
#include <cstdlib>
#include <cassert>

class Stack {
public:
  const int data;
  const Stack* previous;

  Stack(const int data, const Stack* previous) :
    data(data),
    previous(previous) {
  }
};

const Stack* const emptyStack() {
  return NULL;
}

bool isEmpty(const Stack* const stack) {
  return stack == emptyStack();
}

const Stack* const push(const Stack* const stack, int val) {
  return new Stack(val, stack); // ok
}

int peek(const Stack* const stack) {
  return stack->data;
}

const Stack* const pop(const Stack* const stack) {
  return stack->previous;
}

const Stack* const reverse(const Stack* const stack,
      const Stack* const answer = emptyStack()) {
  if (isEmpty(stack))
    return answer;
  else
    return reverse(stack->previous, push(answer, stack->data));
}

Coada

Să se implementeze o coadă, cu operațiile emptyQueue, isEmpty, push, pop și peek.

class Queue {
public:
  const Stack* const first;
  const Stack* const second;

  Queue(const Stack* const first, const Stack* const second) :
    first(first),
    second(second) {
    ;
  }
};

const Queue* const emptyQueue() {
  return new Queue(emptyStack(), emptyStack());
}

bool isEmpty(const Queue* const queue) {
  return queue == emptyQueue();
}

const Queue* const push(const Queue* const queue, int val) {
  return new Queue(push(queue->first,val), queue->second);
}

const Queue* const pop(const Queue* const queue) {
  if (isEmpty(queue->second))
    return new Queue(emptyStack(), pop(reverse(queue->first)));
  else
    return new Queue(queue->first, pop(queue->second));
}

int peek(const Queue* const queue) {
  if (isEmpty(queue->second))
    return peek(reverse(queue->first));
  else
    return queue->second->data;
}

Heap-ul

Să se implementeze operațiile: emptyHeap, isEmpty, push, peek și pop într-un Min Heap.

class Heap {
public:
  int data;
  const Heap* const left;
  const Heap* const right;

  Heap(int data, const Heap* const left, const Heap* const right) :
    data(data),
    left(left),
    right(right) {
    ;
  }
};

const Heap* const emptyHeap() {
  return NULL;
}

bool isEmpty(const Heap* const heap) {
  return heap == emptyHeap();
}

const Heap* const push(const Heap* const heap, int val) {
  if (isEmpty(heap)) {
    return new Heap(val, emptyHeap(), emptyHeap());
  } else if (heap->data < val) {
    if (rand() % 2 == 0)
      return new Heap(heap->data, heap->left, push(heap->right, val));
    else
      return new Heap(heap->data, push(heap->left, val), heap->right);
  } else { // val < heap->data
    if (rand() % 2 == 0)
      return new Heap(val, heap->left, push(heap->right, heap->data));
    else
      return new Heap(val, push(heap->left, heap->data), heap->right);
  }
}

int peek(const Heap* const heap) {
  return heap->data;
}

const Heap* const pop(const Heap* const heap) {
  assert(!isEmpty(heap));
  if (isEmpty(heap->left) && isEmpty(heap->right))
    return emptyHeap();
  else if (isEmpty(heap->right))
    return heap->left;
  else if (isEmpty(heap->left))
    return heap->right;
  else if (heap->left->data < heap->right->data)
    return new Heap(heap->left->data, pop(heap->left), heap->right);
  else // heap->right->data < heap->left->data
    return new Heap(heap->right->data, heap->left, pop(heap->right));
}

Testarea implementării

Să se testeze structurile de date implementate anterior.

int main() {
  printf("Stack: ");
  const Stack* const s1 = emptyStack();
  const Stack* const s2 = push(s1, 1);
  printf("%d ", peek(s2));
  const Stack* const s3 = push(s2, 2);
  printf("%d ", peek(s3));
  const Stack* const s4 = push(s3, 3);
  printf("%d ", peek(s4));
  const Stack* const s5 = pop(s4);
  printf("%d ", peek(s5));
  const Stack* const s6 = pop(s5);
  printf("%d ", peek(s6));
  const Stack* const s7 = push(s6, 4);
  printf("%d ", peek(s7));
  const Stack* const s8 = push(s7, 5);
  printf("%d ", peek(s8));
  const Stack* const s9 = pop(s8);
  printf("%d ", peek(s9));
  const Stack* const s10 = pop(s9);
  printf("%d\n", peek(s10));

  printf("Queue: ");
  const Queue* const q1 = emptyQueue();
  const Queue* const q2 = push(q1, 1);
  printf("%d ", peek(q2));
  const Queue* const q3 = push(q2, 2);
  printf("%d ", peek(q3));
  const Queue* const q4 = push(q3, 3);
  printf("%d ", peek(q4));
  const Queue* const q5 = pop(q4);
  printf("%d ", peek(q5));
  const Queue* const q6 = pop(q5);
  printf("%d ", peek(q6));
  const Queue* const q7 = push(q6, 4);
  printf("%d ", peek(q7));
  const Queue* const q8 = push(q7, 5);
  printf("%d ", peek(q8));
  const Queue* const q9 = pop(q8);
  printf("%d ", peek(q9));
  const Queue* const q10 = pop(q9);
  printf("%d\n", peek(q10));

  printf("Heap: ");
  const Heap* const h1 = emptyHeap();
  const Heap* const h2 = push(h1, 6);
  printf("%d ", peek(h2));
  const Heap* const h3 = push(h2, 4);
  printf("%d ", peek(h3));
  const Heap* const h4 = push(h3, 8);
  printf("%d ", peek(h4));
  const Heap* const h5 = pop(h4);
  printf("%d ", peek(h5));
  const Heap* const h6 = pop(h5);
  printf("%d ", peek(h6));
  const Heap* const h7 = push(h6, 7);
  printf("%d ", peek(h7));
  const Heap* const h8 = push(h7, 5);
  printf("%d ", peek(h8));
  const Heap* const h9 = pop(h8);
  printf("%d ", peek(h9));
  const Heap* const h10 = pop(h9);
  printf("%d\n", peek(h10));
  return 0;
}