Download presentation
Presentation is loading. Please wait.
Published byLiana Kusnadi Modified over 5 years ago
1
ECE 103 Engineering Programming Chapter 62 Stack Implementation
Herbert G. Mayer, PSU CS Status 6/4/2014 Initial content copied verbatim from ECE 103 material developed by Professor Phillip PSU ECE
2
Syllabus Array – Version 1 Array – Version 2 Pointer Version
3
Stack : Array – Version 1 A stack can be implemented as an array of structures. A separate “stack index” variable determines the index of the stack’s top element. A B C top D Stack “push” operation “pop” operation 2
4
Define structure of stack element
struct element_def { int val; /* Element value */ }; typedef struct element_def ELEMENT; typedef enum { FALSE, TRUE } boolean; typedef enum { E_OK, E_STK_EMPTY, E_STK_FULL } e_stat; 3
5
Create and initialize the stack
#define MAX_STACK_SIZE 5 int main (void) { ELEMENT stack[MAX_STACK_SIZE]; /* Stack as raw array */ int stk_idx = -1; /* Top-of-stack index */ int v1 = 7, v2; /* Stack value */ /* Perform some stack operations */ if (push(stack, &stk_idx, v1) == E_STK_FULL) printf("Stack is full.\n"); if (!is_empty(stk_idx)) pop(stack, &stk_idx, &v2) return 0; } stk_idx -1 4 {?} 3 2 1 stack 4
6
Check if the stack is empty
boolean is_empty (const int stk_idx) { return (stk_idx == -1) ? TRUE : FALSE; } Pre-State: stack empty Check if stack empty stk_idx -1 stk_idx -1 returns 1 4 {?} 3 2 1 stack 4 {?} 3 2 1 stack 5
7
Push a value on top of the stack
e_stat push (ELEMENT stack[], int *stk_idx, int value) { if (*stk_idx >= MAX_STACK_SIZE-1) return E_STK_FULL; (*stk_idx)++; /* Update top-of-stack index */ stack[*stk_idx].val = value; /* Push value */ return E_OK; } stk_idx→ -1 value 7 stk_idx→ value 7 4 {?} 3 2 1 stack→ Pre-State: empty stack Want to push 7 on stack 4 {?} 3 2 1 stack→ {7} 6
8
Pop a value off the top of the stack
e_stat pop (ELEMENT stack[], int *stk_idx, int *value) { if (is_empty(*stk_idx)) return E_STK_EMPTY; *value = stack[*stk_idx].val; /* Pop value */ (*stk_idx)--; /* Update top-of-stack index */ return E_OK; } stk_idx→ value→ ? stk_idx→ -1 value→ 7 4 {?} 3 2 1 stack→ {7} Pre-State: 7 on stack Want to pop 7 off stack 4 {?} 3 2 1 stack→ {7} 7
9
Retrieve value at the top of the stack
e_stat peek (const ELEMENT stack[], int const stk_idx, int *value) { if (is_empty(stk_idx)) return E_STK_EMPTY; *value = stack[stk_idx].val; /* Retrieve value */ return E_OK; } Note: The stack is not changed. The top-of-stack value is retrieved but not popped. 8
10
Stack : Array – Version 2 In this version, the stack array and the stack index variable are stored together in a structure. This helps to “hide” some of the internal workings of the stack implementation. A B C top D Stack “push” operation “pop” operation 9
11
Define structure of stack element and stack
#define MAX_STACK_SIZE 5 /* Stack element */ struct element_def { int val; /* Element value */ }; typedef struct element_def ELEMENT; /* Stack itself */ struct stack_def int n; /* Top-of-stack index */ ELEMENT A[MAX_STACK_SIZE]; /* Stack array */ typedef struct stack_def STACK; 10
12
Create the stack int main (void) {
STACK stack; /* Stack as array within structure */ int v1 = 7, v2; /* Stack value */ init_stack(&stack); /* Initialize stack */ /* Perform some stack operations */ if (push(&stack, v1) == E_STK_FULL) printf("Stack is full.\n"); if (!is_empty(&stack)) pop(&stack, &v2) return 0; } stack→ n -1 4 {?} 3 2 1 A 11
13
Initialize the stack void init_stack (STACK *stack) {
stack->n = -1; } stack→ n {?} stack→ n -1 4 {?} 3 2 1 A 4 {?} 3 2 1 A 12
14
Check if the stack is empty
boolean is_empty (const STACK *stack) { return (stack->n == -1) ? TRUE : FALSE; } Pre-State: empty stack Check if stack empty stack→ n -1 stack→ n -1 returns 1 4 {?} 3 2 1 A 4 {?} 3 2 1 A 13
15
Push a value on top of the stack
e_stat push (STACK *stack, const int value) { if (stack->n >= MAX_STACK_SIZE-1) return E_STK_FULL; stack->n++; /* Update top-of-stack index */ stack->A[stack->n].val = value; /* Push value */ return E_OK; } stack→ n -1 value 7 stack→ n value 7 4 {?} 3 2 1 A Pre-State: empty stack Want to push 7 on stack 4 {?} 3 2 1 A {7} 14
16
Pop a value off the top of the stack
e_stat pop (STACK *stack, int *value) { if (is_empty(stack)) return E_STK_EMPTY; *value = stack->A[stack->n].val; /* Pop value */ stack->n--; /* Update top-of-stack index */ return E_OK; } stack→ n value→ ? stack→ n -1 value→ 7 4 {?} 3 2 1 A {7} Pre-State: 7 on stack Want to pop 7 off stack 4 {?} 3 2 1 A {7} 15
17
Retrieve value at the top of the stack
e_stat peek (const STACK *stack, int *value) { if (is_empty(stack)) return E_STK_EMPTY; *value = stack->A[stack->n].val; /* Retrieve value */ return E_OK; } Note: The stack is not changed. The top-of-stack value is retrieved but not popped. 16
18
Stack : Pointer Version
In this version, the stack is implemented as a linked list using pointers. Nodes are created at runtime using malloc(). A B C top D Stack “push” operation “pop” operation 17
19
Define structure of stack element
struct stack_element { int val; /* Element value */ struct stack_element *next; /* Pointer to next element */ }; typedef struct stack_element stack_e; typedef enum { FALSE, TRUE } boolean; typedef enum { E_OK, E_STK_EMPTY, E_STK_FULL } e_stat; 18
20
Create the stack int main (void) {
stack_e *tos = NULL; /* Top-of-stack pointer */ int v1 = 7, v2; /* Element value */ if (push(&tos, v1) == E_STK_FULL) printf("Stack is full.\n"); if (push(&tos, 42) == E_STK_FULL) if (pop(&tos, &v2) == E_STK_EMPTY) printf("Stack is empty.\n"); return 0; } 19
21
After initialization, the stack now looks like this:
tos NULL 20
22
Check if the stack is empty
boolean is_empty (const stack_e *top) { return (top == NULL) ? TRUE : FALSE; } 21
23
Push a value on top of the stack
e_stat push (stack_e **top, const int value) { stack_e *new_element; /* Pointer to new element */ /* Dynamically create new element */ if ( (new_element = (stack_e *) malloc(sizeof(stack_e))) == NULL ) return E_STK_FULL; new_element->val = value; /* Push value */ new_element->next = *top; /* Create link to current top-of-stack */ *top = new_element; /* Update top-of-stack pointer */ return E_OK; } 22
24
e_stat push (stack_e **top, const int value) ← called with push(&tos, v1) where v1=7
NULL value 7 stack_e *new_element; ← create a pointer to a stack element new_element ? new_element = (stack_e *) malloc(sizeof(stack_e)) ← dynamically allocate storage for one element new_element val ? next new_element->val = value; ← val is 7 new_element->next = *top; ← next points to whatever *top (i.e. tos) points to new_element val 7 next NULL *top = new_element; ← tos now points to the newly allocated element. top tos val 7 next NULL top and new_element disappear once the function is done. The dynamically allocated element still exists and is pointed to by tos. new_element 23
25
By performing one push operation, the stack now looks like this:
tos val 7 next NULL 24
26
e_stat push (stack_e **top, const int value) ← called with push(&tos, 42)
7 next NULL value 42 stack_e *new_element; ← create a pointer to a stack element new_element ? new_element = (stack_e *) malloc(sizeof(stack_e)) ← dynamically allocate storage for one element new_element val ? next new_element->val = value; ← val is 42 new_element->next = *top; ← next points to whatever *top (i.e. tos) points to new_element val 42 next val 7 next NULL *top = new_element; ← tos now points to the newly allocated element. top tos val 42 next val 7 next NULL new_element 25
27
By performing another push operation, the stack now looks like this:
tos val 42 next val 7 next NULL 26
28
Pop a value off the top of the stack
e_stat pop (stack_e **top, int *value) { stack_e *p; /* Work pointer to current top-of-stack */ if (is_empty(*top)) return E_STK_EMPTY; *value = (*top)->val; /* Pop value */ p = *top; /* Remember current top-of-stack */ *top = (*top)->next; /* Update top-of-stack pointer */ free(p); /* Deallocate old top-of-stack element */ return E_OK; } 27
29
28 e_stat pop (stack_e **top, int *value) ← called with pop(&tos, &v2)
42 next val 7 next NULL value v2 ? *value = (*top)->val; ← retrieve the value on top of the stack value v2 42 p = *top; ← make p point to the element on the top of the stack p val 42 next val 7 next NULL top tos *top = (*top)->next; ← reset the top-of-stack pointer p val 42 next val 7 next NULL top tos free(p); deallocate the former top-of-stack memory block p val 7 next NULL top tos 28
30
By performing one pop operation, the stack now looks like this:
tos val 7 next NULL 29
31
Retrieve value at the top of the stack
e_stat peek (const stack_e *top, int *value) { if (is_empty(top)) return E_STK_EMPTY; *value = top->val; /* Retrieve value */ return E_OK; } Note: The stack is not changed. The top-of-stack value is retrieved but not popped. 30
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.