• Tidak ada hasil yang ditemukan

Implementing a Stack Using an Array

Dalam dokumen Pelajari tentang Advanced topics in Java (Halaman 113-117)

Stacks and Queues

4.2 Stacks

4.2.1 Implementing a Stack Using an Array

To simplify the presentation of the basic principles, we will work with a stack of integers. Later, we will see how to implement a stack for a general data type.

In the array implementation of a stack (of integers), we use an integer array (ST, say) for storing the numbers and an integer variable (top, say) that contains the subscript of the item at the top of the stack.

Since we are using an array, we will need to know its size in order to declare it. We will need to have some information about the problem to determine a reasonable size for the array. We will use the symbolic constant MaxStack. If we attempt to push more than MaxStack elements onto the stack, a stack overflow error will be reported.

We begin our definition of the class Stack as follows:

public class Stack {

final static int MaxStack = 100;

int top = -1;

int[] ST = new int[MaxStack];

//the rest of the class goes here } //end class Stack

Valid values for top will range from 0 to MaxStack-1. When we initialize a stack, we will set top to the invalid subscript -1.

We can now declare a stack variable, S, with this statement:

Stack S = new Stack();

When this statement is executed, the situation in memory can be represented by that shown in Figure 4-1.

This represents an empty stack. We will need a function that tells us whether a stack is empty. We can add the following instance method to the Stack class:

public boolean empty() { return top == -1;

}

This simply checks whether top has the value -1.

The major operations on a stack are push and pop. To push an item, n, onto a stack, we must store it in ST and update top to point to it. The basic idea is as follows:

add 1 to top set ST[top] to n

However, we must guard against trying to add something to the stack when it is already full. The stack is full when top has the value MaxStack - 1, the subscript of the last element. In this case, we will report that the stack is full and halt the program. Here is the instance method, push, in the Stack class:

S

0 1 2 3 4 5

ST -1 top

Figure 4-1. Array representation of stack in memory

public void push(int n) { if (top == MaxStack - 1) {

System.out.printf("\nStack Overflow\n");

System.exit(1);

} ++top;

ST[top] = n;

} //end push

To illustrate, after the numbers 36, 15, 52, and 23 have been pushed onto S, our picture in memory looks like Figure 4-2.

Finally, to pop an item off the stack, we return the value in location top and decrease top by 1. The basic idea is as follows:

set hold to ST[top]

subtract 1 from top return hold

Again, we must guard against trying to take something off an empty stack. What should we do if the stack is empty and pop is called? We could simply report an error and halt the program. However, it might be better to return some

“rogue” value, indicating that the stack is empty. We take the latter approach in our function pop. Here is the instance method pop in the Stack class:

public int pop() {

if (this.empty())return RogueValue; //a symbolic constant int hold = ST[top];

--top;

return hold;

}

Note that even though we have written pop to do something reasonable if it is called and the stack is empty, it is better if the programmer establishes that the stack is not empty (using the empty function) before calling pop.

Given the class Stack, we can now write Program P4.1, which reads some numbers, terminated by 0, and prints them in reverse order. Note that the word public is dropped from the class Stack in order to store the entire program in one file, StackTest.java.

S

0

36 15 52 23

1 2 3 4 5

ST top 3

Figure 4-2. Stack view after pushing 36, 15, 52, and 23

Program P4.1

import java.util.*;

public class StackTest {

public static void main(String[] args) { Scanner in = new Scanner(System.in);

Stack S = new Stack();

System.out.printf("Enter some integers ending with 0\n");

int n = in.nextInt();

while (n != 0) { S.push(n);

n = in.nextInt();

}

System.out.printf("\nNumbers in reverse order\n");

while (!S.empty())

System.out.printf("%d ", S.pop());

System.out.printf("\n");

} //end main } //end StackTest class Stack {

final static int MaxStack = 100;

final static int RogueValue = -999999;

int top = -1;

int[] ST = new int[MaxStack];

public boolean empty() { return top == -1;

}

public void push(int n) { if (top == MaxStack - 1) {

System.out.printf("\nStack Overflow\n");

System.exit(1);

} ++top;

ST[top] = n;

} //end push public int pop() {

if (this.empty())return RogueValue; //a symbolic constant int hold = ST[top];

--top;

return hold;

}

} //end class Stack

The following shows a sample run of Program P4.1:

Enter some integers ending with 0 1 2 3 4 5 6 7 8 9 0

Numbers in reverse order 9 8 7 6 5 4 3 2 1

It is important to observe that the code in main that uses the stack does so via the functions push, pop, and empty and makes no assumption about how the stack elements are stored. This is the hallmark of an abstract data type—it can be used without the user needing to know how it is implemented.

Next, we will implement the stack using a linked list, but main will remain the same for solving the problem of printing the numbers in reverse order.

Dalam dokumen Pelajari tentang Advanced topics in Java (Halaman 113-117)