9c. Stacks

2021-03-05
slides.com/jod/pt_9c

Docent: Jo Devriendt

Assistent: Ann Philips

Coördinator: Joost Vennekens

voornaam.achternaam@kuleuven.be

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Twee operaties

  • Push: voeg toe aan het einde
  • Pop: neem weg van het einde
void push(Stack* s, char c);
char pop(Stack* s);

element 1

element 2

element 3

element 4

element 5

frame 4

frame 4

frame 4

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Twee operaties

  • Push: voeg toe aan het einde
  • Pop: neem weg van het einde
void push(Stack* s, char c);
char pop(Stack* s);

element 1

element 2

element 5

element 4

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Implementatie via dynamische array

#define WAARDE char

typedef struct {
  int lengte;
  int gereserveerd;
  WAARDE* waardes;
} Stack;

Stack create() {
  Stack stk = {0, 0, NULL};
  return stk;
}

void destroy(Stack* stk){
  if(stk->waardes!=NULL){
    free(stk->waardes);
    stk->lengte = 0;
    stk->gereserveerd = 0;
    stk->waardes = NULL;
  }
}
#define WAARDE char

typedef struct {
  int lengte;
  int gereserveerd;
  WAARDE* waardes;
} Stack;



Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Reserveer

void reserveer(Stack* stk, int k){
  stk->waardes = realloc(stk->waardes, sizeof(WAARDE)*k);
  stk->gereserveerd = k;
  if(stk->lengte > k){
    stk->lengte = k;
  }
}
  • Reserveer geheugen voordat het nodig is
  • lengte is altijd hoogstens gereserveerd
  • Bvb. gereserveerd==5, lengte==2

?

?

?

element 2

element 1

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Push

  • Als dynamische array te klein is, reserveer meer geheugen
  • Bewaar element op index lengte van de array
  • Increment lengte
typedef struct {
  int lengte;       // 0
  int gereserveerd; // 0 
  WAARDE* waardes;  // NULL
} Stack;

initieel

void push(Stack* stk, WAARDE x){
  if(stk->lengte==stk->gereserveerd){
    reserveer(stk, 2*stk->lengte+1);
  }
  stk->waardes[stk->lengte]=x;
  stk->lengte++;
}

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Push

  • Als dynamische array te klein is, reserveer meer geheugen
  • Bewaar element op index lengte van de array
  • Increment lengte
typedef struct {
  int lengte;       // 1
  int gereserveerd; // 1
  WAARDE* waardes;  // ...
} Stack;

na push(..., 'a');

'a'

void push(Stack* stk, WAARDE x){
  if(stk->lengte==stk->gereserveerd){
    reserveer(stk, 2*stk->lengte+1);
  }
  stk->waardes[stk->lengte]=x;
  stk->lengte++;
}

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Push

  • Als dynamische array te klein is, reserveer meer geheugen
  • Bewaar element op index lengte van de array
  • Increment lengte

?

'b'

'a'

typedef struct {
  int lengte;       // 2
  int gereserveerd; // 3
  WAARDE* waardes;  // ...
} Stack;

na push(..., 'b');

void push(Stack* stk, WAARDE x){
  if(stk->lengte==stk->gereserveerd){
    reserveer(stk, 2*stk->lengte+1);
  }
  stk->waardes[stk->lengte]=x;
  stk->lengte++;
}

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Push

void push(Stack* stk, WAARDE x){
  if(stk->lengte==stk->gereserveerd){
    reserveer(stk, 2*stk->lengte+1);
  }
  stk->waardes[stk->lengte]=x;
  stk->lengte++;
}
  • Als dynamische array te klein is, reserveer meer geheugen
  • Bewaar element op index lengte van de array
  • Increment lengte

'b'

'a'

typedef struct {
  int lengte;       // 3
  int gereserveerd; // 3
  WAARDE* waardes;  // ...
} Stack;

na push(..., 'c');

'c'

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Pop

WAARDE pop(Stack* stk){
  stk->lengte--;
  WAARDE tmp = stk->waardes[stk->lengte];
  if(stk->lengte<=stk->gereserveerd/2){
    reserveer(stk,stk->gereserveerd/2);
  }
  return tmp;
}
  • Decrement lengte
  • Als meer gereserveerd wordt dan momenteel in gebruik, reserveer minder geheugen

'b'

'a'

typedef struct {
  int lengte;       // 3
  int gereserveerd; // 3
  WAARDE* waardes;  // ...
} Stack;

na push(..., 'c');

'c'

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Pop

WAARDE pop(Stack* stk){
  stk->lengte--;
  WAARDE tmp = stk->waardes[stk->lengte];
  if(stk->lengte<=stk->gereserveerd/2){
    reserveer(stk,stk->gereserveerd/2);
  }
  return tmp;
}
  • Decrement lengte
  • Als veel meer gereserveerd wordt dan momenteel in gebruik, reserveer minder geheugen

?

'b'

'a'

typedef struct {
  int lengte;       // 2
  int gereserveerd; // 3
  WAARDE* waardes;  // ...
} Stack;

na pop();

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Pop

WAARDE pop(Stack* stk){
  stk->lengte--;
  WAARDE tmp = stk->waardes[stk->lengte];
  if(stk->lengte<=stk->gereserveerd/2){
    reserveer(stk,stk->gereserveerd/2);
  }
  return tmp;
}
  • Decrement lengte
  • Als meer gereserveerd wordt dan momenteel in gebruik, reserveer minder geheugen

'a'

typedef struct {
  int lengte;       // 1
  int gereserveerd; // 1
  WAARDE* waardes;  // ...
} Stack;

na pop();

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Voorbeeld main

void main() {
  Stack stk = create();
  Stack* sptr = &stk;
  push(sptr,'h');
  push(sptr,'e');
  push(sptr,'l');
  push(sptr,'l');
  push(sptr,'o');
  push(sptr,'\0');
  printf("stk: %s\n", stk.waardes);
  for(int i=0; i<3; ++i){
    printf("pop: %c\n", pop(sptr));
  }
  push(sptr,'\0');
  printf("stk: %s\n", stk.waardes);
  destroy(sptr);
}
$ ./a.out
stk: hello
pop: 
pop: o
pop: l
stk: hel

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Waarom factor 2?

void push(Stack* stk, WAARDE x){
  if(stk->lengte==stk->gereserveerd){
    reserveer(stk, 2*stk->lengte+1);
  }
  stk->waardes[stk->lengte]=x;
  stk->lengte++;
}

WAARDE pop(Stack* stk){
  stk->lengte--;
  WAARDE tmp=stk->waardes[stk->lengte];
  if(stk->lengte<=stk->gereserveerd/2){
    reserveer(stk,stk->gereserveerd/2);
  }
  return tmp;
}
  • realloc kopieert alle data: lineair aantal operaties - O(n)
  • niet bij elke push of pop herhalen: reserveer meer dan nodig
  • "Geamortiseerd" levert dit een constant aantal operaties per push/pop

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Oefening

  • Implementeer stack m.b.v. dubbelgelinkte lijst

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Samenvatting

  • Stack is een lineaire datastructuur met twee operaties
    • push
    • pop
  • Implementatie kan met
    • dubbelgelinkte lijst
    • dynamische arrays
      • reserveer meer geheugen dan strikt nodig om lineaire overhead te minimaliseren

9c. Stacks

By Jo Devriendt