Professional Documents
Culture Documents
Thai Java 3
Thai Java 3
่ ก
แพร่หลาย ซึง่ การจัดเก็บในรูปแบบทัง้ สองนี้ได ้เลียนแบบมาจากเหตุการณ์ทเี่ กิดขึน ้ ใน
ิ ประจาวันของเรา เช่น เราวางหนั งสือซ ้อนกันเป็ นชัน้ ๆ (Stack) หรือ การเข ้าแถวเพือ
ชีวต ่ รอรับ
การบริการต่าง ๆ หรือทีเ่ รียกจนติดปากว่า เข ้าคิว (Queue) เช่น เข ้ารอการนาเงินไปฝากกับ
ธนาคาร เข ้าคิวรอซือ ้ ตั๋วหนัง ในบทนีเ้ ราจะพูดถึง Stack และ Queue ทีใ่ ช ้ array และ Linked-
List เป็ นโครงสร ้างในการเก็บข ้อมูล
หลังจากจบบทเรียนนีแ
้ ล ้ว ผู ้อ่านจะได ้ทราบถึง
3.1 Stack
Stack เป็ นการจัดเก็บข ้อมูลในแบบทีเ่ รียกว่า Last-In, First-Out (LIFO) ซึง่ เป็ นการจัดเก็บที่
สามารถนาไปใช ้กับการเขียนโปรแกรมด ้านต่าง ๆ เช่น การตรวจสอบ (parsing หรือ analyzing)
สมการทางคณิตศาสตร์ เช่น 3 * (5 + 89) ในการออกแบบทางสถาปั ตยกรรมของ computer
ส่วนใหญ่กใ็ ช ้ stack เป็ นตัวจัดเก็บ address หรือ instruction ต่าง ๆ
้ – stack of books
ภาพที่ 3.1 การวางหนั งสือเรียงกันเป็ นชัน
เราเริม
่ ต ้นด ้วยการสร ้าง class ArrayStack ทีม
่ ี operation ต่าง ๆ ทีเ่ กีย
่ วข ้องกับ stack คือ การ
นาข ้อมูลเข ้า (push) การดึงข ้อมูลออก (pop) การตรวจสอบว่า stack มีข ้อมูลอยูเ่ ต็มหรือไม่ม ี
ข ้อมูลอยูเ่ ลย (full และ empty) หรือแม ้กระทั่งการแสดงข ้อมูลทีม ่ อ
ี ยูใ่ น stack
ใน class ArrayStack ของเรา เรากาหนดตัวแปรชือ ่ stack เป็ น array ทีใ่ ช ้ในการเก็บ object ที่
user ต ้องการใช ้ และ กาหนดให ้ top เป็ นตัวชีถ
้ งึ ข ้อมูลทีอ
่ ยูบ
่ นสุดของ stack ขนาดของ stack
จะมาจาก user เมือ ่ constructor ถูกเรียก เช่น
การนาข ้อมูลเข ้าสู่ stack ก็เหมือนกับการนาข ้อมูลเข ้าสู่ array โดยทั่วไป เราเลือกทีจ่ ะตรวจสอบ
ถึงความจุของ stack ก่อนทีเ่ ราจะนาข ้อมูลเข ้า ซึง่ ถ ้า stack ของเราเต็มแล ้ว เราก็จะฟ้ องไปยัง
user ทันที (และจะไม่ใส่ข ้อมูลให ้)
Book 6
Book 6 Top
Book 2 Book 2
Book 1 Book 1
70
บทที่ 3 Stack และ Queue
public T pop() {
if(empty())
return null;
return stack[top--];
}
Book 6
Book 4 Book 4
Book 3 Book 3
Book 2 Book 2
Book 1 Book 1
เพือ
่ ให ้การจัดการกับข ้อมูลเป็ นไปได ้อย่างหลากหลาย เราจะกาหนดให ้ stack ของเราเก็บข ้อมูล
ในรูปแบบของข ้อมูลดิบ (Generic)1 ซึง่ วิธก ี ารดังกล่าวก็ทาได ้ง่าย ๆ ดังทีเ่ ห็นจากโปรแกรม
ArrayStack.java ทีเ่ ราเขียนขึน ้
1: /**
2: Stack using array to store data
3: accommodate any-type from user (almost)
4: */
5:
6: class ArrayStack<T> {
7: private int size;
8: private T[] stack;
9: private int top, numItems;
10:
11: //set size and allocate space for stack
12: public ArrayStack(int max) {
13: size = max; //set size of stack
14: stack = (T[])new Object[size]; //allocate space
15: top = -1; //no object yet
16: numItems = 0;
17: }
1
เราไม่สามารถสร ้าง array สาหรับการเก็ บ generic ได ้ ดังนัน ้ เราจึงต ้องสร ้าง stack ทีใ่ ช ้เก็ บ Object ก่อน หลังจากนัน
้
จึง cast ให ้เป็ น generic ดังทีเ่ ห็ นในบรรทัดที่ 14 อย่างไรก็ตาม ถ ้าเรา compile ด ้วย –Xlint:unchecked เราจะพบว่า
Java จะเตือนเราถึงการใช ้ cast ทีอ ่ าจเกิดปั ญหา (stack เป็ น Object[] แต่เราบังคับให ้เป็ น T[])
71
Stack และ Queue บทที่ 3
18:
19: //insert object onto stack
20: public void push(T obj) {
21: if(!full()) {
22: stack[++top] = obj;
23: numItems = top + 1;
24: }
25: else {
26: System.err.println("ERROR! Stack is full.");
27: System.exit(1);
28: }
29: }
30:
31: //remove object from stack
32: public T pop() {
33: if(empty())
34: return null;
35: return stack[top--];
36: }
37:
38: //check if stack is full
39: public boolean full() {
40: return (top == size-1);
41: }
42:
43: //check if stack is empty
44: public boolean empty() {
45: return (top == -1);
46: }
47:
48: public String toString() {
49: StringBuffer buf = new StringBuffer();
50: buf.append("top-> " + stack[top]);
51: for(int i = top-1; i >= 0; i--)
52: buf.append(", " + stack[i]);
53: return new String(buf);
54: }
55: }
1: /**
2: Testing stack that uses array as storage
3: */
4:
5: class ArrayStackTest {
6: public static void main(String []args) {
7: //create a stack holding 10 items
8: ArrayStack<Integer> stack = new ArrayStack<Integer>(10);
9:
10: //push 10 Integers onto stack
11: stack.push(45);
12: stack.push(5);
13: stack.push(32);
14: stack.push(78);
15: stack.push(12);
16: stack.push(99);
17: stack.push(27);
18: stack.push(19);
19: stack.push(66);
20: stack.push(7);
21:
22: System.out.println(stack); //display contents
72
บทที่ 3 Stack และ Queue
23:
24: //remove all Integers from stack
25: while(!stack.empty())
26: System.out.println("Pop " + stack.pop() +
" from Stack");
27: }
28: }
เรานาข ้อมูลทีเ่ ป็ น Object ชนิด Integer ใส่ไว ้ใน stack ของเราจนเต็มทัง้ 10 ตัว หลังจากนัน
้
เราก็ pop ข ้อมูลทัง้ หมดออกจาก stack ด ้วยการใช ้ while/loop (และ method empty() ในการ
ตรวจสอบว่า stack นั น ้ ยังมีข ้อมูลอยูอ
่ ก
ี หรือไม่)
จากคุณสมบัตข ิ อง stack ทีว่ า่ last-in, first-out ทาให ้เราสามารถนา stack มาใช ้ในการ
reverse string ได ้ง่าย ๆ ดังตัวอย่างทีแ ่ สดงให ้ดูนี้
1: /**
2: Using stack to reverse a string
3: */
4:
5: import static java.lang.System.out;
6:
7: class ReverseTest {
8: public static void main(String[] args) {
9: //if no input detect, exit with a message
10: if(args.length == 0) {
11: out.println("Usage: java
ReverseTest \"Your String\"");
12: System.exit(1);
13: }
14:
15: //calling reverse() with args[0] and display its result
16: out.println("Reversed string: " + reverse(args[0]));
17: }
18:
19: //reversing input string
20: public static String reverse(String input) {
21: String output = ""; //output string
22: int size = input.length(); //size of input string
23: ArrayStack<Character> stack = new ArrayStack<Character>(size);
24:
25: //pushing each character onto stack
26: for(int i = 0; i < input.length(); i++) {
27: char c = input.charAt(i); //get a char from string
28: stack.push(c); //push it onto stack
29: }
30:
31: //pop character from stack and put it in output
32: while(!stack.empty()) {
73
Stack และ Queue บทที่ 3
ขัน
้ ตอนการทาก็ไม่ยาก เมือ ่ เราได ้ string มาจาก keyboard แล ้วเราก็ทาการดึงเอา character
ออกจาก string ทีละตัว แล ้วนาไปใส่ไว ้ใน stack เมือ ่ ใส่ไว ้หมดแล ้วเราก็จะมี stack ทีม่ ข
ี ้อมูล
ด ้านบนเป็ น character ตัวสุดท ้ายของ string ทีอ ่ า่ นเข ้ามา ทีนี้เมือ
่ เรา pop ข ้อมูลออกจาก
stack เราก็จะได ้ข ้อมูลตัวสุดท ้ายของ string ก่อน และตัวอืน ่ ๆ ถัดไปจนกว่าเราจะได ้ข ้อมูล
ทัง้ หมด
่ นเลขฐำนสิบให้เป็นเลขฐำนสองด้วยกำรใช ้ stack
3.1.1.4 กำรเปลีย
stack สามารถทีจ ่ ะนามาใช ้ในการเปลีย่ นเลขฐาน 10 ให ้เป็ นเลขฐาน 2 ได ้เป็ นอย่างดี วิธก ี ารใน
การเปลีย ่ นเลขฐานสิบให ้เป็ นเลขฐานสองนัน ้ ให ้เรานาสองไปหารเลขนัน ้ แล ้วเก็บเศษทีไ่ ด ้จาก
การหารนั น ้ ใน stack หารไปเรือ่ ย ๆ จนหารไม่ได ้ หลังจากนัน ้ เราก็ pop ข ้อมูลทีอ
่ ยูใ่ น stack
ออก ซึง่ จะเป็ นเลขฐานสองของเลขฐานสิบนั น ้ ดังโปรแกรมตัวอย่างทีใ่ ห ้นี้
1: /**
2: converting positive number in base 10
3: to base 2 using stack
4: */
5:
6: import static java.lang.System.out;
7:
8: class Convert {
9: public static void main(String[] args) {
10: //if no input, exit with a message
11: if(args.length == 0) {
12: out.println("Usage: java Convert number");
13: System.exit(1);
14: }
15: ArrayStack<Integer> numStack = new ArrayStack<Integer>(20);
16: int remainder;
17: int number = Integer.parseInt(args[0]);
18:
19: //find remainder of number%2 and keep
20: //them on stack
21: while(number != 0) {
22: remainder = number % 2;
23: numStack.push(remainder);
24: number /= 2;
25: }
26:
27: //pop all digit from stack
28: out.print("Number in base two: ");
29: while(!numStack.empty()) {
30: out.print(numStack.pop());
31: }
32: }
33: }
74
บทที่ 3 Stack และ Queue
สมการทีอ
่ ยูใ่ นรูปแบบของ postfix จากตัวอย่างก่อนหน ้านี้คอ
ื
342–54+*3+*
ขัน
้ ตอนในการประมวลผล postfix notation มีดังนีค
้ อ
ื
((( 3 + (2 + 5)) * ( 6 + 8 )) - ( 6 * 2 ))
วิธก
ี ารในการเปลีย ่ นก็ไม่ยาก เราเพียงแค่ตรวจสอบดูวา่ ค่าของ exp[i] มีคา่ เป็ นอะไร ถ ้าเป็ น
เครือ่ งหมายของการประมวลผล (+, -, *, /) เราก็จัดเก็บเครือ ่ งหมายเหล่านี้ไว ้ใน stack ถ ้าเป็ น
ตัวเลขเราก็จะเก็บตัวเลขนี้ไว ้ใน buffer ถ ้าเป็ นวงเล็บเปิ ดเราก็จะไม่ทาอะไร แต่ถ ้าเป็ นวงเล็บปิ ด
เราก็จะย ้ายข ้อมูลทีอ ่ ้านบนของ stack (ซึง่ ต ้องเป็ นเครือ
่ ยูด ่ งหมายสาหรับการประมวลผลอย่าง
แน่นอน) ไปเก็บไว ้ใน buffer หลังจากนั น ้ เราก็สง่ postfix นี้ไปทาการประมวลผลต่อไป
75
Stack และ Queue บทที่ 3
switch(exp[i]) {
case '+' : s.push(s.pop() + s.pop());
break;
case '-' : v1 = s.pop();
v2 = s.pop();
s.push(v2 - v1);
break;
case '*' : s.push(s.pop() * s.pop());
break;
case '/' : v1 = s.pop();
v2 = s.pop();
s.push(v2 / v1);
break;
}
//convert digit to int
while(exp[i] >= '0' && exp[i] <= '9')
s.push((double)(exp[i++] - '0'));
return s.pop();
}
และโปรแกรมการทางานทัง้ หมดของการประมวลผลสมการทีอ
่ ยูใ่ นรูปแบบของ postfix มีดังนี้
1: /**
2: Evaluating arithmetic expressions using stack
3: work only for one digit input with no error detecting!
4: */
5:
6: import static java.lang.System.out;
7:
8: class ArithmeticEvaluation {
9: public static void main(String[] args) {
10: if(args.length == 0) {
11: out.println("Usage: ArithmeticEvaluation \"expression\"");
12: out.println("e.g. \"(3 * (2 - 4 ) * (4 / (5 - 2)))\"");
13: System.exit(1);
14: }
15: char []exp = args[0].toCharArray();
16: exp = infixToPostfix(exp);
76
บทที่ 3 Stack และ Queue
กระบวนการในการประมวลผลสมการทีม ่ ต
ี ัวเลขมากกว่า 1 digit นั น
้ เราเพียงแค่เปลีย่ นการอ่าน
สมการจากทีเ่ คยอ่านเป็ นทีละตัวอักษร เราก็อา่ นเป็ นทีละหน่วย (หรือทีเ่ รียกง่าย ๆ ว่าทีละคา –
token) ซึง่ ทาได ้ง่าย ๆ ด ้วยการใช ้ class StringTokenizer ดังตัวอย่างทีแ ่ สดงให ้ดูนี้
77
Stack และ Queue บทที่ 3
if(isOperator(token)) {
v2 = st.pop();
v1 = st.pop();
result = operate(token.charAt(0), v1, v2);
st.push(result);
}
//token is an operand, we push it onto stack
else
st.push(new Double(Double.parseDouble(token)));
เราได ้ดัดแปลง method evaluate() ของเรา ให ้รับ String แทน char[] ซึง่ เราได ้ส่ง String ตัว
นี้ (exp) ไปให ้ StringTokenizer() ทาการอ่านพร ้อมกับแปลงรูปแบบของ exp ให ้อยูใ่ นรูปแบบ
ที่ StringTokenizer ต ้องการ ซึง่ เราได ้เก็บไว ้ในตัวแปร str หลังจากนัน
้ เราก็สร ้าง stack สาหรับ
เก็บ token ทีเ่ ราจะดึงออกมาจาก str
ขัน
้ ตอนต่าง ๆ ทีเ่ หลืออยูก ่ ็เหมือนกับโปรแกรม ArithmeticEvaluation.java ทีเ่ ราเขียนไว ้ก่อน
หน ้านี้ เพียงแต่เราได ้จัดกระบวนการประมวลผลให ้อยูใ่ นรูปแบบของ method เพือ ่ ให ้ดูง่ายขึน
้
และ method ทีเ่ ราเขียนขึน ้ ใหม่คอ
ื
78
บทที่ 3 Stack และ Queue
1: /**
2: Evaluating arithmetic expressions using stack
3: Expression must be fully parenthesized e.g.
4: ((( 3 + (2 + 5)) * ( 6 + 8 )) - ( 6 * 2 ))
5: This version allows more than one digit & no error checking
6: */
7:
8: import static java.lang.System.out;
9: import java.util.StringTokenizer;
10: import java.util.Scanner;
11:
12: class ArithmeticEvaluation2 {
13: public static void main(String[] args) {
14: out.println("Enter infix expression: ");
15: out.print("e.g. \"(((3 + (2 + 5)) * (6 + 8)) - (6 * 2))\" : ");
16: Scanner in = new Scanner(System.in);
17: String exp = in.nextLine();
18:
19: exp = infixToPostfix(exp.toCharArray());
20: out.printf("Result: %.2f%n", evaluate(exp));
21: }
22:
23: //converts to postfix form
24: public static String infixToPostfix(char[] exp) {
25: System.out.println("Infix form: " + new String(exp));
26: ArrayStack<Character> s = new ArrayStack<Character>(exp.length);
27: StringBuffer buf = new StringBuffer();
28: for(int i = 0; i < exp.length; i++) {
29: if(exp[i] == ')')
30: buf.append(" " + s.pop() + " ");
31: if(exp[i] == '+' || exp[i] == '-' ||
exp[i] == '*' || exp[i] == '/')
32: s.push(exp[i]);
33: if(exp[i] >= '0' && exp[i] <= '9')
34: buf.append(exp[i]);
35: if(exp[i] == ' ') buf.append(" ");
36: }
37: return new String(buf);
38: }
39:
40: //evaluates postfix form
41: public static Double evaluate(String exp) {
42: System.out.println("Postfix form: " + new String(exp));
43: StringTokenizer str = new StringTokenizer(exp);
44: ArrayStack<Double> st = new ArrayStack<Double>(str.countTokens());
45: String token;
46: Double v1, v2, result = 0.0D;
47:
48: //until all tokens have been processed
49: while(str.hasMoreTokens()) {
50: token = str.nextToken();
51: //token is an operator, we pop 2 operands and
52: //perform operation on them - push result onto stack
53: if(isOperator(token)) {
54: v2 = st.pop();
55: v1 = st.pop();
56: result = operate(token.charAt(0), v1, v2);
57: st.push(result);
58: }
59: //token is an operand, we push it onto stack
60: else
61: st.push(new Double(Double.parseDouble(token)));
62:
79
Stack และ Queue บทที่ 3
เมือ
่ ทดสอบด ้วยสมการ (((30 + (20 + 50)) * (60 + 80)) - (60 * 20)) ผลลัพธ์ทเี่ ราได ้คือ
เนื่องจากว่าเราไม่มขี ้อจากัดในเรือ
่ งของจานวนของข ้อมูลทีส ่ ามารถเก็บได ้ใน Stack ดังนัน้ ใน
การนาข ้อมูลเข ้าเราจึงไม่ต ้องตรวจสอบว่า Stack ของเราจะเต็มหรือไม่ (ในมุมมองของผู ้ใช ้
Stack ของเรา) เพียงแต่เราต ้องมาเพิม ่ ขนาดความจุให ้กับ array ของเราถ ้า array นั น ้ ไม่
สามารถรองรับการนาเข ้าข ้อมูลใหม่ได ้ เรามาเริม
่ ด ้วยการดู class DynamicArrayStack ก่อน
หลังจากนัน้ เราจะมาดูกน ั ถึง method ต่าง ๆ ทีม
่ อ
ี ยูใ่ น class นี้
1: /**
2: Use dynamic array to store objects
3: */
4:
5: import java.lang.reflect.Array;
6:
7: class DynamicArrayStack<T> {
8: private T[] stack;
9: private int top, numItems;
80
บทที่ 3 Stack และ Queue
DynamicArrayStack() {
stack = (T[])new Object[INITIAL_CAPACITY];
top = -1;
numItems = 0;
}
81
Stack และ Queue บทที่ 3
หลังจากทีท
่ ดลองด ้วยโปรแกรม TestDynamicArrayStack.java ดังทีเ่ ห็นด ้านล่างนี้
1: /**
2: Testing dynamic stack
3: */
4:
5: class TestDynamicArrayStack {
6: public static void main(String[] args) {
7: //create stack
8: DynamicArrayStack<Integer> stack = new DynamicArrayStack<Integer>();
9:
10: //create 15 random Integer objects
11: //and insert them onto stack
12: for(int i = 0; i < 15; i++) {
13: int data = (int)(Math.random() * 100 + 1);
14: stack.push(data);
15: }
16: System.out.println(stack); //display contents of stack
17:
18: //remove 8 objects from stack
19: for(int i = 0; i < 8; i++) {
20: stack.pop();
21: }
22: System.out.println(stack); //display contents again
23: }
24: }
ผลลัพธ์ทไี่ ด ้คือ
top -> 30, 92, 51, 35, 94, 85, 76, 55, 18, 33, 25, 2, 42, 70, 47
top -> 18, 33, 25, 2, 42, 70, 47
เรานาข ้อมูลทีเ่ ป็ น Integer ใส่เข ้าสู่ Stack จานวน 15 ตัวเพือ่ แสดงให ้เห็นว่า Stack ของเรา
ขยายความจุให ้เราโดยอัตโนมัต ิ (เรารู ้ว่าความจุเริม ่ ต ้นของเรามีคา่ เป็ น 10) หลังจากนัน
้ เราก็
แสดงผลผ่านทาง standard output เราทาการลบข ้อมูลออก 8 ตัวพร ้อมกับแสดงผลของข ้อมูล
ทีเ่ หลืออยูใ่ น Stack เพือ
่ ยืนยันว่าการทางานของ Stack นั น ้ ถูกต ้อง
82
บทที่ 3 Stack และ Queue
ผู ้อ่านจะเห็นว่าโครงสร ้างของ Stack ทีเ่ ราสร ้างขึน้ ใหม่นัน ้ ทางานรองรับการนาเข ้าได ้ดีกว่าทีเ่ รา
ได ้ออกแบบไว ้ก่อนหน ้านี้ เราไม่ต ้องกังวลถึงความจุทจ ี่ ากัดของ Stack อีกต่อไป อย่างไรก็ตาม
โครงสร ้างของ Stack ทีเ่ ราได ้ออกแบบไว ้ยังมีอก ี หลายส่วนทีส ่ ามารถนาไปปรับปรุงเพือ ่ ให ้การ
ใช ้งานทาได ้ง่ายขึน้ เช่น ในการ pop ข ้อมูลออกจาก Stack นั น ้ เรายังต ้องทาการ cast ให ้อยูใ่ น
รูปของ object ทีเ่ ราได ้กาหนดไว ้ คงจะเป็ นสิง่ ทีด
่ ถ ี ้าเราสามารถทีจ ่ ะรองรับการนาข ้อมูลเข ้า และ
ออกจาก Stack โดยไม่ต ้องทาการ cast หรือกังวลกับชนิดของข ้อมูลทีเ่ รากาลังทาอยู่
3.2 Queue
Queue เป็ นโครงสร ้างทีเ่ ก็บข ้อมูลในรูปแบบทีเ่ รียกว่า First In, First Out (เข ้าก่อน – ออก
ก่อน) หรือ FIFO queue มาจากภาษาอังกฤษทีแ ่ ปลว่า การจัดอันดับ หรือ การจัดแถว ดังที่
แสดงในภาพที่ 3.4
queue ทีเ่ ราจะเขียนขึน ้ ก็จะยังคงใช ้ array เป็ นตัวเก็บข ้อมูล แต่เราจะใช ้ array ทีน ่ าเอาเนื้อทีท
่ ี่
ว่างลงเมือ ่ มีการดึงข ้อมูลออกไปกลับมาใชใหม่ ้ วิธน
ี ี้จะทาให ้เรามีท ี่ ทีส
่ ามารถจะจัดเก็บข ้อมูลได ้
ดีกว่า array แบบปกติ เราเรียก array แบบนี้วา่ circular array ผู ้อ่านอาจใช ้ array ธรรมดาใน
การเก็บข ้อมูลก็ได ้ แต่การบริหารและจัดการกับเนื้อทีม ่ ป
ี ั ญหามากกว่าการจัดเก็บด ้วย circular
array กล่าวคือเมือ ่ มีการนาข ้อมูลเข ้า เราจะนาไปใส่ไว ้ที่ rear และเลือ ่ นไปอีกหนึง่ ตาแหน่ง และ
เมือ่ ดึงออกเราก็ดงึ ออกจากทาง front และก็เลือ ่ นไปอีกหนึง่ ตาแหน่ง วิธก ี ารแบบนี้ทาให ้เราเสีย
เนื้อทีท่ างด ้านหน ้าของ array เมือ่ เราดึงข ้อมูลออก ดังทีแ ่ สดงในภาพที่ 3.5 นี้
front rear
55 78 12 7 85 23 77 235 …
เนือ
้ ทีส
่ ญ
ู เสียหลังจากการดึงข ้อมู ลออก
เนื่องจาก queue เป็ นโครงสร ้างทีน ่ าข ้อมูลเข ้าสู่ queue ทางด ้านหลังและดึงข ้อมูลออกทาง
ด ้านหน ้า ดังนัน
้ การเขียน code จะต ้องจาตาแหน่งของข ้อมูลทัง้ ทีอ ่ ยูด
่ ้านหน ้าและด ้านหลังของ
queue อีกสิง่ หนึง่ ทีเ่ ราจะต ้องคานึงถึงก็คอื การตรวจสอบว่า queue เต็ม (full) หรือว่าง
(empty) เนื่องจาก circular queue นาเอาช่องว่างทีเ่ หลืออยูม ่ าใช ้ ดังนั น
้ การตรวจสอบจึงต ้อง
ใช ้ index 2 ตัวเป็ นตัวช่วย
(front == rear)
83
Stack และ Queue บทที่ 3
0 1 2 3 4
rear
้
เนื่องจากว่าเราใชการค านวณด ้วย (rear + 1) % size == front เป็ นตัวตรวจสอบความจุเต็ม
ของ queue ดังนัน ้ เราจะเสียช่องว่างไปหนึง่ ที่ ดังทีแ
่ สดงในภาพที่ 3.7
0 1 2 3 4
สมมติวา่ มีการดึงข ้อมูลออกจาก queue 2 ตัวหลังจากที่ queue เต็ม เราก็นาช่องว่างที่ rear ชี้
่ าใช ้ พร ้อมทัง้ ทาการกาหนดตาแหน่งของ rear ใหม่ให ้รองรับการใส่ข ้อมูลด ้วยการวนกลับ
อยูม
ของ rear ดังทีแ ่ สดงให ้ดูในภาพที่ 3.8
84
บทที่ 3 Stack และ Queue
0 1 2 3 4
45 89 23 10
อย่างไรก็ตามถ ้าสังเกตให ้ดีจะเห็นว่า ถ ้าเราให ้ผู ้ใช ้กาหนดขนาดของ queue ให ้เป็ น n โดยที่ n
เป็ นค่า integer ทีเ่ ป็ นบวก queue ของเราจะสามารถเก็บข ้อมูลได ้สูงสุดได ้เพียง n – 1 ตัว (เช่น
ทีแ
่ สดงให ้ดูในภาพก่อนหน ้านี)้ เพราะฉะนัน ้ ถ ้าเราอยากให ้การกาหนดค่าของผู ้ใช ้เป็ นจริงดังที่
เขากาหนดเราก็เพียงแต่เพิม ่ ขนาด (size) ของ queue ให ้มีคา่ เกินไปหนึง่ ค่า ดังทีแ
่ สดงไว ้ใน
constructor ของ QueueArray (size = max + 1)
ในบางครัง้ เราอาจเพิม
่ ตัวแปรอีกตัวหนึง่ (count) เพือ
่ เป็ นตัวบอกว่ามีข ้อมูลอยูใ่ น queue กีต
่ ัว
และการเพิม ่ ตัวแปรตัวนี้อาจช่วยให ้การเขียน code ของการทางานของ queue เขียนได ้ง่ายขึน ้
โปรแกรมตัวอย่างของเราใชตั้ วแปร count ในการแสดงผลมากกว่าทีจ ่ ะใช ้ทาอย่างอืน ่ ดังที่
แสดงไว ้ใน constructor ทีเ่ ห็นนี้
ในทางปฏิบัตน ิ ัน
้ เมือ
่ front และ rear มาอยูใ่ นตาแหน่งทีอ ่ ยูถ
่ ัดกัน การตรวจสอบว่า queue เต็ม
นั น
้ จะทาให ้การ insert ข ้อมูลตัวสุดท ้ายเป็ นไปไม่ได ้ เพราะว่าประโยค
จะทาให ้เราเสียช่องว่างใน queue ไปหนึง่ ช่องดังทีไ่ ด ้กล่าวมาแล ้ว แต่เพือ ่ ให ้ผู ้ใช ้มีความรู ้สึกว่า
ได ้ใช ้ queue อย่างทีเ่ ขากาหนดไว ้ (โดยไม่รู ้ว่าการใช ้เนื้อทีใ่ นหน่วยความจานั น้ มีการใช ้เกิน)
่ ขนาดของการใช ้ภายใน queue มากกว่าการจองใช ้จริงจากผู ้ใช ้
เราจึงต ้องเพิม
การ insert ข ้อมูลเข ้าสู่ queue ของเราก็ทาได ้ด ้วยการตรวจสอบว่า queue ของเรานั น ้ เต็มหรือ
ยังด ้วยการเรียก method full() ถ ้ายังไม่เต็มก็ใส่เข ้าไปและเลือ
่ น rear pointer ไปอีกหนึง่ ช่อง
ด ้วยการใช ้คาสัง่
85
Stack และ Queue บทที่ 3
การ remove ข ้อมูลออกจาก queue ก็ทาคล ้าย ๆ กับการ insert เพียงแต่แทนทีเ่ ราจะทากับ
rear pointer เราก็มาทากับ front pointer เมือ ่ เราดึงข ้อมูลออกแล ้ว (เก็บไว ้ในทีเ่ ก็บชัว่ คราว)
เราก็ต ้องเลือ
่ น front pointer ของเราให ้อยูใ่ นทีท่ เี่ หมาะสม ด ้วยการใช ้คาสัง่
public T remove() {
//exit routine if queue is empty
if(empty()) {
System.err.println("Error: queue is EMPTY!");
System.exit(2);
}
T temp = queue[front]; //remove object
queue[front] = null; //set queue[front] to null
front = (front + 1) % size; //move front pointer
count--; //one object less
return temp; //return removed object
}
1: /**
2: Queue using array to store data
3: */
4:
5: class QueueArray<T> {
6: private int size; //size of queue
7: private int count; //# of objects in queue
8: private T[] queue; //space for objects
9: private int front, rear; //front and rear pointers
10:
11: public QueueArray(int max) {
12: size = max + 1; //one size bigger
13: queue = (T[])new Object[size];
14: front = rear = 0; //initial queue: empty
15: count = 0; //no object in queue
16: }
17:
18: //insert object into queue
19: public void insert(T obj) {
20: //exit routine if queue is full
21: if(full()) {
22: System.err.println("Error: queue is FULL!");
23: System.exit(1);
24: }
25: queue[rear] = obj; //insert object
26: rear = (rear + 1) % size; //move rear pointer
27: count++; //one more object added
28: }
86
บทที่ 3 Stack และ Queue
29:
30: //remove object from array
31: public T remove() {
32: //exit routine if queue is empty
33: if(empty()) {
34: System.err.println("Error: queue is EMPTY!");
35: System.exit(2);
36: }
37: T temp = queue[front]; //remove object
38: queue[front] = null; //set queue[front] to null
39: front = (front + 1) % size; //move front pointer
40: count--; //one object less
41: return temp; //return removed object
42: }
43:
44: //when rear pointer is right next to front pointer
45: private boolean full() {
46: if((rear + 1) % size == front)
47: return true;
48: else
49: return false;
50: }
51:
52: //when rear is at the same position as front
53: private boolean empty() {
54: if(rear == front)
55: return true;
56: else
57: return false;
58: }
59:
60: //display queue's content
61: public void printQ() {
62: System.out.print("(" + queue[0]);
63: for(int i = 1; i < queue.length; i++)
64: System.out.print(", " + queue[i]);
65: System.out.println(")");
66: }
67:
68: //count empty spaces
69: public int emptySpaces() {
70: return size - count - 1;
71: }
72: }
หลังจากทีท
่ ดลอง run ดูด ้วยโปรแกรมทีเ่ ห็นนี้
1: /**
2: Testing module for queue
3: */
4:
5: import static java.lang.System.out;
6:
7: class TestQueueArray {
8: public static void main(String[] args) {
9: QueueArray<Integer> queue = new QueueArray<Integer>(10);
10:
11: //insert random Integers into queue
12: out.println("Insert 10 items into queue");
13: for(int i = 0; i < 10; i++) {
14: int object = (int)(Math.random() * 10);
15: queue.insert(object);
16: queue.printQ(); //for viewing purpose only
17: }
18: out.print("Queue after insertion: ");
19: queue.printQ();
20: out.println("Spaces left = " + queue.emptySpaces());
21:
22: //remove 5 objects from queue
23: out.println("\nRemove 5 items from queue");
24: for(int j = 0; j < 5; j++) {
25: Integer object = (Integer)queue.remove();
26: queue.printQ(); //for viewing purpose only
87
Stack และ Queue บทที่ 3
27: }
28: out.print("Queue after removal: ");
29: queue.printQ();
30: out.println("Spaces left = " + queue.emptySpaces());
31:
32: //insert 4 more random Integers into queue
33: out.println("\nInsert 4 items into queue");
34: for(int i = 0; i < 4; i++) {
35: Integer object = new Integer((int)(Math.random() * 10));
36: queue.insert(object);
37: queue.printQ(); //for viewing purpose only
38: }
39: out.print("Queue after insertion: ");
40: queue.printQ();
41: out.println("Spaces left = " + queue.emptySpaces());
42: }
43: }
Queue ทีเ่ ราเขียนขึน ้ ยังเป็ น queue ทีใ่ ช ้กันอยูโ่ ดยทั่วไป ยังมี queue อยูอ่ ก
ี หลายแบบทีม่ ก
ี าร
จัดเก็บข ้อมูลแตกต่างออกไป เช่น priority queue ซึง่ เป็ น queue ทีใ่ ช ้ในระบบปฏิบัตก ิ ารใน
แบบ multitasking ในการเก็บข ้อมูลของ queue แบบนี้จะต ้องมีการจัดเก็บตาม priority ทีไ่ ด ้
กาหนดไว ้ ซึง่ อาจเป็ นเงือ ่ นไขใด ๆ ก็ได ้ทีท ่ าให ้ข ้อมูลใน queue มีการจัดเก็บแบบมี order เช่น
ให ้ข ้อมูลทีม
่ ค
ี า่ น ้อยทีส
่ ด
ุ เป็ นข ้อมูลทีม
่ ี priority สูงสุดและการจัดเก็บก็จัดเก็บแบบมากไปหาน ้อย
88
บทที่ 3 Stack และ Queue
0 1 2 3 4
ข ้อมูลทีม ่ ี
55 50 44 35 33 Priority
สูงทีส่ ด
ุ
ข ้อมูลทีม่ ี
Priority น ้อย
ทีส
่ ด
ุ ตาแหน่งของ
42 42
1: /**
2: Priority Queue using array + smallest key has high priority
3: */
4:
5: class PriorityQ<T> {
6: private int size, elems;
7: private T[] que;
8:
9: PriorityQ(int max) {
10: size = max;
11: elems = 0;
12: que = (T[])new Object[size];
13: }
14:
15: //insert object into que in descending order
16: public void insert(T value) {
17: int i;
18: for(i = 0; i < elems; i++) {
19: if(((Comparable)que[i]).compareTo(value) < 0)
20: break;
21: }
22: //shift positions
23: for(int j = elems; j > i; j--)
24: que[j] = que[j - 1];
25: //insert element
26: que[i] = value;
27: elems++;
28: }
29:
30: //remove item from queue
31: public T remove() {
32: return que[--elems];
33: }
34:
35: //display contents via System.out.println()
36: public String toString() {
37: StringBuffer buf = new StringBuffer();
38: buf.append("rear->(" + que[0]);
39: for(int i = 1; i < elems; i++)
40: buf.append(", " + que[i]);
41: return new String(buf + ")<-front");
42: }
43: }
89
Stack และ Queue บทที่ 3
เราคงไม่ต ้องอธิบายมากมายนั กในเรือ ่ งของ code ทีใ่ ห ้ด ้านบนนี้ ผู ้อ่านได ้สัมผัสกับการนาข ้อมูล
เข ้าแบบจัดเรียงมาก่อนหน ้านี้แล ้ว ส่วนการนาข ้อมูลออกนั น ้ เราใช ้คาสัง่
return que[--elems];
1: /**
2: Testing priority queue
3: */
4:
5: import static java.lang.System.out;
6:
7: class TestPriorityQ {
8: public static void main(String[] args) {
9: //create 10 items priority queue
10: PriorityQ<Integer> q = new PriorityQ<Integer>(10);
11: int data;
12:
13: //populate queue with 10 random Integers
14: for(int i = 0; i < 10; i++) {
15: data = (int)(Math.random() * 100) + 1;
16: q.insert(data);
17: }
18: out.println("Queue after inserted 10 items");
19: out.println(q); //display contents of queue
20:
21: //remove 5 items from queue
22: for(int i = 0; i < 5; i++) {
23: data = q.remove();
24: out.println("Removed: " + data);
25: }
26: out.println("Queue after removed 5 items");
27: out.println(q); //display contents of queue
28:
29: //insert 2 more items
30: q.insert(99);
31: q.insert(37);
32: out.println("Queue after inserted 2 more items");
33: out.println(q); //display contents of queue
34: }
35: }
ผลลัพธ์ทไี่ ด ้คือ
90
บทที่ 3 Stack และ Queue
ArrayList เป็ นโครงสร ้างที่ Java มีให ้สาหรับการทางานกับข ้อมูลทีถ ่ ูกเก็บในลักษณะของ list
หรือ array (ดูบททีห่ นึง่ ) เราจะใช ้ method ต่าง ๆ จาก ArrayList มาช่วยในการจัดการกับข ้อมูล
ของ Stack และ Queue โดยก่อนอืน ่ เราจะมาดูกน
ั ถึงการสร ้าง Stack จาก ArrayList ทีว่ า่
1: /**
2: Stack using ArrayList to manipulate data
3: */
4:
5: import java.util.ArrayList;
6:
7: public class ArrayListStack<T> {
8: private ArrayList<T> list;
9: private int top;
10:
11: //default constructor
12: public ArrayListStack() {
13: list = new ArrayList<T>();
14: top = -1;
15: }
16:
17: //insert item onto stack
18: public void push(T item) {
19: list.add(++top, item);
20: }
21:
22: //remove item from stack
23: public T pop() {
24: return list.remove(top--);
25: }
26:
27: //display content of stack
28: public String toString() {
29: StringBuffer buf = new StringBuffer();
30: buf.append("(" + list.get(0));
31: for(int i = 1; i < list.size(); i++)
32: buf.append(", " + list.get(i));
33: return new String(buf + ")<-top");
34: }
35:
36: //testing module
37: public static void main(String[] args) {
38: //create new stack
39: ArrayListStack<String> stk = new ArrayListStack<String>();
40:
41: //insert 4 items and display content
42: stk.push("Java");
43: stk.push("C++");
44: stk.push("Visual Basic");
45: stk.push("C#");
46: System.out.println(stk);
47:
48: //remove an item and display content afterward
49: System.out.println("Pop " + stk.pop());
50: System.out.println(stk);
51: }
52: }
เราใช ้ method add() สาหรับการ push ใช ้ method remove() สาหรับการ pop ส่วนการ
แสดงผลเราใช ้ get() เป็ นตัวดึงข ้อมูลออกจาก ArrayList ตาม index ทีก
่ าหนดให ้ ผลลัพธ์ทเี่ รา
ได ้จากการ run คือ
1: /**
91
Stack และ Queue บทที่ 3
92
บทที่ 3 Stack และ Queue
Java มี class Stack ทีเ่ ราสามารถเรียกใช ้ได ้เหมือนกับ class ตัวอืน่ ๆ โปรแกรมตัวอย่างต่อไปนี้
เป็ นการแสดงการใช ้ class Stack พร ้อมกับการใช ้ for/in loop ทีม ่ อ
ี ยูใ่ น Java 1.5
1: /**
2: Stack from Java (1.5)
3: */
4:
5: import java.util.Stack;
6:
7: class JavaStack {
8: public static void main(String[] args) {
9: Stack<String> stk = new Stack<String>();
10:
11: //push items onto stack
12: stk.push("Chiang Mai");
13: stk.push("Chiang Rai");
14: stk.push("Chiang Kong");
15:
16: printStack(stk);
17:
18: //pop items from stack
19: System.out.println("Pop: " + stk.pop());
20: printStack(stk);
21: }
22:
23: //iterate over stack's content
24: public static void printStack(Stack<String> stack) {
25: System.out.println("Content:");
26: for(String s : stack) {
27: System.out.println(s);
28: }
29: }
30: }
ค่าทีอ ่ งหมาย <> จะเป็ นตัวบอกชนิดของข ้อมูลทีเ่ ราต ้องการเก็บใน stack ซึง่ ถ ้าเรา
่ ยูใ่ นเครือ
ต ้องการเก็บ Integer เราก็เพียงแค่ประกาศ
stk.push("Chiang Mai");
93
Stack และ Queue บทที่ 3
สาหรับการแสดงข ้อมูลทัง้ หมดทีม ี ยูใ่ น stack เราเรียกใช ้ for/in loop ซึง่ เป็ น for-loop ตัวใหม่
่ อ
ที่ Java 1.5 มีให ้ วิธกี ารเข ้าหาข ้อมูลทีเ่ ราใช ้ก็คอ ื บอกชนิดของข ้อมูลทีเ่ ราเก็บไว ้ใน stack
ให ้กับ for/in loop ด ้วยการประกาศตัวแปร s ให ้เป็ น String พร ้อมกับบอกทีอ ่ ยูท
่ ี่ string เหล่านี้
ถูกเก็บไว ้ ซึง่ ก็คอ
ื stk (หรือตัวแปรทีช ่ อ ี้ ยูท
่ เี่ ดียวกัน เช่น stack)
for(String s : stack) {
System.out.println(s);
}
เมือ
่ เรา run โปรแกรม JavaStack.java ผลลัพธ์ทเี่ ราได ้คือ
Content:
Chiang Mai
Chiang Rai
Chiang Kong
Pop: Chiang Kong
Content:
Chiang Mai
Chiang Rai
ผู ้อ่านควรใช ้เวลาสักเล็กน ้อยในการศึกษาถึงการใช ้ Stack (หรือแม ้แต่ Queue) ที่ Java มีให ้
จากคูม ่ อ
ื ทีม
่ ใี ห ้จาก sun เพือ
่ ให ้เกิดความเข ้าใจมากยิง่ ขึน
้ ตัวอย่างต่อไปจะเป็ นตัวอย่างสุดท ้าย
ในบทนี้ทเี่ รียกใช ้ class PriorityQueue ของ Java
1: /**
2: Java's PrioirtyQueue
3: */
4:
5: import java.util.PriorityQueue;
6:
7: class JavaPriorityQueue {
8: public static void main(String[] args) {
9: PriorityQueue<String> q = new PriorityQueue<String>();
10:
11: //insert 4 items
12: q.offer("Chiang Mai");
13: q.offer("Bangkok");
14: q.offer("Ayudhaya");
15: q.offer("Nakhon Nayok");
16:
17: //display items in queue
18: for(String s : q)
19: System.out.println(s);
20:
21: //remove 1 item
22: System.out.println("Item removed: " + q.poll());
23: }
24: }
เรานาข ้อมูลชนิด String เข ้าสู่ queue ด ้วยการเรียกใช ้ method offer() และดึงข ้อมูลออกด ้วย
การเรียกใช ้ poll() ทัง้ นี้ผู ้อ่านสามารถเรียกใช ้ method add() และ method remove() ทีม ่ ใี ห ้ก็
ได ้ การจัดวางข ้อมูลใน priority queue ของ Java นั น ้ จัดวางตาม natural order ของข ้อมูลที่
นาเข ้า ด ้วยการใช ้ comparable interface เป็ นตัวกาหนด
Ayudhaya
Chiang Mai
Bangkok
Nakhon Nayok
94
บทที่ 3 Stack และ Queue
เราได ้ออกแบบ Stack ทีใ่ ช ้ array เป็ นตัวจัดเก็บข ้อมูลมาก่อนหน ้านี้ ณ เวลานี้เราจะทดลองใช ้
Linked-List เป็ นตัวเก็บข ้อมูลของ Stack ซึง่ เป็ นสิง่ ทีท
่ าได ้ไม่ยากดังทีจ
่ ะแสดงให ้เห็นด ้วย
code ข ้างล่างนี้ (ดู class MyLinkedList ในบทที่ 2)
1: /**
2: Stack using Linked-List as storage
3: */
4:
5: public class LinkedStack<T extends Comparable<? super T>> {
6: protected MyLinkedList<T> list;
7:
8: //default constructor
9: //calling LinkedList's constructor
10: public LinkedStack() {
11: list = new MyLinkedList<T>();
12: }
13:
14: //insert item onto Stack using LinkedList's insert()
15: public void push(T item) {
16: list.insert(item);
17: }
18:
19: //remove item from Stack using LinkedList's remove()
20: public T pop() {
21: //cannot remove if empty
22: if(empty())
23: return null;
24: //return item removed from list
25: return list.remove();
26: }
27:
28: //calling LinkedList's empty()
29: public boolean empty() {
30: return list.size() == 0;
31: }
32:
33: //display contents of list via System.out.println()
34: public String toString() {
35: //if empty, display top->()
36: //otherwise return new String to avoid null
37: //pointer exception in System.out.println()
38: if(empty()) {
39: System.out.println("top->()");
40: return new String();
41: }
42: //items are in list - display them
43: else {
44: StringBuffer buf = new StringBuffer();
45: buf.append("top->(" + list.peek(0));
46: for(int i = 1; i < list.size(); i++)
47: buf.append(", " + list.peek(i));
48: buf.append(")");
49: return new String(buf);
50: }
51: }
52: }
95
Stack และ Queue บทที่ 3
หลังจากทีท
่ ดสอบด ้วยโปรแกรมทีเ่ ห็นนี้
1: /**
2: Testing stack that uses LinkedList stores data
3: */
4:
5: class LinkedStackTest {
6: public static void main(String []args) {
7: LinkedStack<Character> stack = new LinkedStack<Character>();
8:
9: //populate stack with chars
10: for(char i = 'A'; i <= 'K'; i++) {
11: stack.push(i);
12: System.out.println(stack);
13: }
14:
15: //remove 5 items form Stack
16: for(int i = 0; i < 5; i++) {
17: stack.pop();
18: System.out.println(stack);
19: }
20:
21: //insert 2 more chars
22: stack.push('Z');
23: stack.push('Q');
24: System.out.println(stack);
25: }
26: }
ผลลัพธ์ทไี่ ด ้คือ
top->(A)
top->(B, A)
top->(C, B, A)
top->(D, C, B, A)
top->(E, D, C, B, A)
top->(F, E, D, C, B, A)
top->(G, F, E, D, C, B, A)
top->(H, G, F, E, D, C, B, A)
top->(I, H, G, F, E, D, C, B, A)
top->(J, I, H, G, F, E, D, C, B, A)
top->(K, J, I, H, G, F, E, D, C, B, A)
top->(J, I, H, G, F, E, D, C, B, A)
top->(I, H, G, F, E, D, C, B, A)
top->(H, G, F, E, D, C, B, A)
top->(G, F, E, D, C, B, A)
top->(F, E, D, C, B, A)
top->(Q, Z, F, E, D, C, B, A)
1: /**
2: Queue using LinkedList as storage
3: */
4:
96
บทที่ 3 Stack และ Queue
1: class LinkedQueueTest {
2: public static void main(String []args) {
3: LinkedQueue<Character> queue = new
LinkedQueue<Character>();
4:
5: //populate Stack with 10 random Integers
6: for(char c = 'Z'; c > 'K'; c--) {
7: queue.insert(c);
8: System.out.println(queue);
9: }
10:
11: //remove 5 items form queue
12: for(int i = 0; i < 5; i++) {
13: queue.remove();
14: System.out.println(queue);
15: }
16:
97
Stack และ Queue บทที่ 3
ผลลัพธ์ทไี่ ด ้คือ
front->(Z)<-rear
front->(Z, Y)<-rear
front->(Z, Y, X)<-rear
front->(Z, Y, X, W)<-rear
front->(Z, Y, X, W, V)<-rear
front->(Z, Y, X, W, V, U)<-rear
front->(Z, Y, X, W, V, U, T)<-rear
front->(Z, Y, X, W, V, U, T, S)<-rear
front->(Z, Y, X, W, V, U, T, S, R)<-rear
front->(Z, Y, X, W, V, U, T, S, R, Q)<-rear
front->(Z, Y, X, W, V, U, T, S, R, Q, P)<-rear
front->(Z, Y, X, W, V, U, T, S, R, Q, P, O)<-rear
front->(Z, Y, X, W, V, U, T, S, R, Q, P, O, N)<-rear
front->(Z, Y, X, W, V, U, T, S, R, Q, P, O, N, M)<-rear
front->(Z, Y, X, W, V, U, T, S, R, Q, P, O, N, M, L)<-rear
front->(Y, X, W, V, U, T, S, R, Q, P, O, N, M, L)<-rear
front->(X, W, V, U, T, S, R, Q, P, O, N, M, L)<-rear
front->(W, V, U, T, S, R, Q, P, O, N, M, L)<-rear
front->(V, U, T, S, R, Q, P, O, N, M, L)<-rear
front->(U, T, S, R, Q, P, O, N, M, L)<-rear
front->(U, T, S, R, Q, P, O, N, M, L, A, B)<-rear
สรุป
แบบฝึ กห ัด
่ ง่ ค่าของข ้อมูลทีอ
1. จงเขียน method ทีส ่ ยูด
่ ้านล่างสุด (bottom) ของ stack ให ้กับผู ้เรียก ให ้
เขียนโปรแกรมทดสอบ method ทีเ่ ขียนขึน ้
2. จงเขียน method ทีส ่ ง่ ค่าของข ้อมูล ณ ตาแหน่งทีก ่ าหนดให ้ (nth element) ของ stack
(นั บจากด ้านบน หรือ top) ให ้กับผู ้เรียก ให ้เขียนโปรแกรมทดสอบ
3. จงเขียนโปรแกรมทีท
่ าหน ้าทีส ่ ้านล่าง (top to bottom)
่ ลับข ้อมูลของ stack จากด ้านบนสูด
98
บทที่ 3 Stack และ Queue
4. จงเขียนโปรแกรมทีม
่ ี menu สาหรับการทางานต่าง ๆ ทีเ่ กีย ่ วข ้องกับ stack เช่น push,
pop, peek, จานวนข ้อมูลทีม
่ อ
ี ยูใ่ น stack และ display ข ้อมูลทีม ่ อ
ี ยูใ่ น stack ทัง้ หมด
6. จงเขียนโปรแกรมทีส
่ ลับตาแหน่งข ้อมูลใน queue (front to rear)
11. กาหนดให ้ queue เป็ น queue ทีเ่ ก็บข ้อมูลชนิด Integer จงเขียน method ที่ delete
ข ้อมูลทีเ่ ป็ น negative ทัง้ หมดออกจาก queue โดยทีข่ ้อมูลทีเ่ หลืออยูใ่ น queue ยังคงอยู่
ในตาแหน่งทีเ่ รียงกันอยูแ ่ บบเดิม (same order)
12. จงเขียน method ทีส ่ ง่ ค่า true ถ ้า queue 2 ตัวมีข ้อมูลเหมือนกัน และส่งค่า false ถ ้ามี
ข ้อมูลทีแ
่ ตกต่างกัน
13. จงเขียนโปรแกรมทีน
่ าเอา stack และ queue มาอยูใ่ น menu เดียวกัน (ข ้อ 4 รวมกับข ้อ 5)
16. จงเขียนโปรแกรมทีใ่ ช ้ class Vector เป็ นโครงสร ้างหลักในการเก็บข ้อมูลของ Queue และ
Stack ให ้เขียนโปรแกรมทดสอบ method ต่าง ๆ ทีม ่ อ
ี ยูใ่ น Queue และ Stack ทีส
่ ร ้างขึน
้
17. จงสร ้าง class Stack ทีม ่ อมให ้ผู ้ใชน้ าข ้อมูลเข ้า หรือดึงข ้อมูลออก ณ
่ ี method ทีย
ตาแหน่งทีก ่ าหนดให ้
จงเขียนโปรแกรมทีแ ้
่ สดงการใชโครงสร ้างดังกล่าว โดยมีกระบวนการทีเ่ กีย
่ วข ้องกับ queue
ทัง้ หมด เช่น การนาข ้อมูลเข ้า การดึงข ้อมูลออก เป็ นต ้น
20. จงสร ้าง class PriorityQueue ทีใ่ ช ้ class ArrayList เป็ นโครงสร ้างหลักในการเก็บข ้อมูล
โดยมีเงือ
่ นไขว่า ข ้อมูลทีม
่ ี priority สูงสุดจะต ้องอยูด
่ ้านหลังสุดของ queue เท่านั น
้ และให ้
เขียนโปรแกรมทดสอบโครงสร ้างดังกล่าว
99
Stack และ Queue บทที่ 3
21. กาหนดให ้มี queue อยูส ่ องตัว โดยทีต ่ ัวแรกเป็ น queue ทีม ่ ก
ี ารจัดเรียงข ้อมูลจากน ้อยไป
หามาก และตัวทีส ่ องเป็ น queue ทีม ่ ก
ี ารจัดเรียงจากมากไปหาน ้อย จงเขียนโปรแกรมทีท ่ า
การรวมเอาข ้อมูลทัง้ สองทีอ ่ ยูใ่ น queue เข ้าด ้วยกันโดยกาหนดให ้ ข ้อมูลหลังจากการรวม
แล ้วให ้อยูใ่ นรูปแบบของการจัดเรียงจาก มากไปหาน ้อย หรือน ้อยไปหามาก ทัง้ นี้จะขึน ้ อยู่
กับข ้อมูลทีอ ่ ยูด
่ ้านหน ้าสุดของ queue ทัง้ สองตัว ถ ้าข ้อมูลตัวแรกสุดของ queue ตัวแรก
น ้อยกว่า ข ้อมูลตัวแรกสุดของ queue ตัวทีส ่ องให ้จัดเรียงจากมากไปหาน ้อย ให ้ทาการ
ตรงกันข ้ามถ ้าข ้อมูลตัวแรกไม่เป็ นไปตามทีก ่ ล่าวไว ้
22. จงออกแบบ stack ทีใ่ ช ้ linked list เป็ นโครงสร ้างหลักในการจัดการข ้อมูล
23. จงออกแบบ queue ทีใ่ ช ้ linked list เป็ นโครงสร ้างหลักในการจัดการข ้อมูล
100