วันอังคารที่ 17 มีนาคม พ.ศ. 2552

เรื่อง Stack

เนื้อหา
- โครงสร้างข้อมูลแบบสแตก
- การดำเนินงานพื้นฐานของสแตก

- การแทนที่ข้อมูลของสแตก
- การประยุกต์ใช้สแตก

จุดประสงค์การเรียนรู้
1. เพื่อให้นักศึกษาทราบโครงสร้างข้อมูลแบบสแตกและการทำงาน
2. เพื่อให้นักศึกษาทราบการดำเนินงานพื้นฐานของสแตก
3. เพื่อให้นักศึกษาทราบการแทนที่ของข้อมูลแบบสแตก
4. เพื่อให้นักศึกษาทราบวิธีการประยุกต์ใช้สแตก

สแตก(Stack)เป็นโครงสร้างข้อมูลที่ ข้อมูลแบบลิเนียร์ลิสต์ ที่มีคุณสมบัติที่ว่าการเพิ่มหรือลบข้อมูลในสแตก จะกระทำที่ปลายข้างเดียวกัน ซึ่งเรียกว่า Topของสแตก (Top Of Stack)และ ลักษณะที่สำคัญของสแตก คือ ข้อมูลที่ใส่หลังสุดจะถูกนำออกมา จากสแตกเป็นลำดับแรกสุด เรียกคุณสมบัตินี้ว่า LIFO (Last In First Out)การดำเนินงานพื้นฐานของสแตกการทำงานต่าง ๆของสแตกจะกระทาที่ปลายข้างหนึ่งของสแตกเท่านั้นดั้งนั้นจะต้องมีตัวชี้ตำแหน่งข้อมูลบนสุดของสแตกด้วยการทำงานของสแตกจะประกอบด้วยกระบวนการ 3กระบวนการที่สำคัญ คือ

1.Push คือ การนำข้อมูลใส่ลงไปในสแตกเช่น สแตก s ต้องการใส่ข้อมูล iในสแตกจะได้ push(s,i)คือ ใส่ข้อมูล i ลงไปที่ท็อปของสแตก sในการเพิ่มข้อมูลลงในสแตก จะต้องทำการ ตรวจสอบว่าสแตก เต็มหรือไม่ ถ้าไม้เต็มก็ สามารถเพิ่มข้อมูลลงไปในสแตกได้แล้วปรับตัวชี้ตำแหน่งให้ไปชี้ที่ตำแหน่งข้อมูลใหม่ ถ้าสแตกเต็ม (Stack Overflow)ก็จะไม่สามารถเพิ่มข้อมูลเขาไปในสแตกได้อีก
2.Pop คือการนำข้อมูลออกจากส่วนบนสุดของสแตกเช่น ต้องการนำข้อมูลออกจากสแตกsไปไว้ที่ตัวแปร iจะได้ i = pop (s)การนำข้อมูลออกจากสแตกถ้าสแตกมีสมาชิกเพียง 1ตัวแล้วนำสมาชิกออกจากสแตก จะเกิดสภาวะสแตกว่าง(Stack Empty) คือ ไม่มีสมาชิกอยู่ในสแตกเลยแต่ถ้าไม่มีสมาชิกในสแตกแล้วทำการ popสแตกจะทำให้เกิดความผิดพลาดที่เรียกว่าStack Underflow เพราะฉะนั้นก่อนนำข้อมูลออกจากสแตกจะต้องตรวจสอบก่อนว่าสแตกว่างหรือเปล่าจึงจะนำข้อมูลออกจากสแตกได้ และ ปรับตัวชี้ตำแหน่งให้ไปชี้ตำแหน่งของข้อมูลที่ต่อจากข้อมูลที่ถูกนำออกไป 3.Stack Top ป็นการคัดลอกข้อมูลที่อยู่บนสุดของสแตกแต่ไม่ได้นำเอาข้อมูลนั้นออกจากสแตกตัวอย่าง
การแทนที่ข้อมูลของสแตก
การแทนที่ข้อมูลของสแตกสามารถทำได้ 2 วิธี คือ
1. การแทนที้ข้อมูลของสแตกแบบลิงค์ลิสต
2. การแทนที่ข้อมูลของสแตกแบบอะเรย์
การแทนที่ข้อมูลของสแตกแบบลิงค์ลิสตจะประกอบไปด้วย 2 ส่วน คือ
1. Head Node จะประกอบไปด้วย 2ส่วนคือ top pointer และจำนวนสมาชิกในสแตก
2. Data Node จะประกอบไปด้วยข้อมูล (Data)และพอยเตอร์ ที่ชี้ไปยังข้อมูล
การดำเนินการเกี่ยวกับสแตกการดำเนินการเกี่ยวกับสแตก ได้แก่
1. Create Stack
2. Push Stack
3. Pop Stack
4. Stack Top
5. Empty Stack
6. Full Stack
7. Stack Count
8. Destroy Stack

1. Create Stack จัดสรรหน่วยความจำให้แก่ Head Nodeและส่งค่าตำแหน่งที่ชี้ไปยัง Head ของสแตกกลับมา

Algorithm CreateStack
Nothing
Post Head node allocated or error returned
Return Pointer to head node or null pointer if no
memory
1. if (memory available)
1 allocate (StackPrt)
2 StackPtr->count=0
3 StackPtr->top=null pointer
2. else
1 StackPtr=null pointer
3. return StackPtr
End
CreateStack

2.Push Stackการเพิ่มข้อมูลลงไปในสแตก


Algorithm PushStack
Pre Stack is a pointer to the stack head structure
Data contains data to pushed into stack
Post Data have been pushed in stack
Return True if successful; False if memory overflow
1. if (stack full)
1 success = false
2. else
1 allocate (newPtr)
2 newPtr->data =data
3 newPtr->next =stack->top
4 stack->top =newPtr
5 stack->count =stack->count+1
6 succes = true
3. return success

3.Pop stack การยำข้อมูลบนสุดออกจากสแตก
Algorithm PopStack
Pre Stack is a pointer to the stack head structure
DataOut is a reference variable to receive the data
Post Data have been returned to calling algorithm
Return True if successful; False if underflow
1. if (stack empty)
1 success = false
2. else
1 dltPtr->data =stack->top
2 dataOut =stack->top->data
3 stack->top =stack->top
4 stack->count =stack->count-1
5 recycle (dltPtr)
6 succes = true
3. return successEnd PopStack

4. Stack Top เป็นการคัดลอกข้อมูลที่อยู่บนสุดของสแตกโดยไม่มีการลบข้อมูลออกจากสแตก
Algorithm StackTop
Pre Stack is a pointer to the stack head structure
DataOut is a reference variable to receive the data
Post Data have been returned to calling algorithm
Return True if data returned; False if underflow
1. if (stack empty)
1 success = false
2. else
1 dataOut = stack->top->data
2 succes = true
3. return successEnd StackTop

5.Empty Stack เป็นการตรวจสอบการวางของสแตกเพื่อไม่ให้เกิดความผิดพลาดในการนำข้อมูลออกจากสแตกที่เรียกว่า Stack Underflow
Algorithm EmptyStack
Pre Stack is a pointer to the stack head structure
Post Returns stack status
Return Boolean, true: stack empty, false: stack contains data
1. if (stack not empty)
1 result = false
2. else
1 result = true
3. return result
End EmptyStack

6. Full Stack เป็นการตรวจสอบว่าสแตกเต็มหรือไม่เพื่อไม่ให้เกิดความผิดพลาดในการนำข้อมูลเข้าสแตกที่เรียกว่า Stack Overflow
Algorithm FullStack
Pre Stack is a pointer to the stack head structure
Post Returns stack status
Return Boolean, true: stack full, false: memory available
1. if (memory available)
1 result = false
2. else
1 result = true
3. return result
End FullStack
7. Stack Count เป็นการนับจำนวนสมาชิกในสแตก
Algorithm StackCount
Pre Stack is a pointer to the stack head structure
Post Returns stack count
Return integer count of number of elements in stack
1. Return (stack->count)
End StackCount

8.Destroy Stack เป็นการลบข้อมูลทั้งหมดที่อยู่ใน สแตก
Algorithm DestroyStack
Pre Stack is a pointer to the stack head structure
Post Stack empty and all nodes recycled
Return null pointer
1. if (stack not empty)
1 loop (stack->top not null)
1 temp = stack->top
2 stack->top = stack->top->link
3 recycle (temp)
Recycle (stack)
Return null pointer
End DestroyStack


Stack Definition for Array Implementation
stackAry dataType>
stackMax
End Stack

การดำเนินการเกี่ยวกับสแตกการดำเนินการเกี่ยวกับสแตก ได้แก่
1. Create Stack
2. Push Stack
3. Pop Stack
4. Stack Top
5. Empty Stack
6. Full Stack
7. Stack Count
8. Destroy Stack

1. Create Stack
Algorithm CreateStack
stackElem contains size of stack
Head node and array allocated or error returned
Return Pointer to head node or null pointer if no memory
1. if (memory not available)
1 StackPtr = null
1 allocate (StackPtr)
2 StackPtr->count = 0
3 StackPtr->top = -1
4 StackPtr->stackMax=stackElem
5 if (memory not available)
1 recycle (StackPtr)
2 StackPtr = null
6 else1 allocate (StackPtr->stackAry)
3. return StackPtr
End CreateStack

2. Push Stack
Algorithm PushStack
Pre Stack is a pointer to the stack head structureData contains data to be pushed into stack
Post Data have been pushed in stack
Return True if successful ; False if memory overflow
1. if (stack->count is at maximum)
1 success = false

1 stack->count = stack->count + 1
2 stack->top = stack->top + 1
3 stack->stackAry[stack->top] = data
4 success = true
3. Return success
End PushStack

3. Pop Stack
Algorithm PushStack
Pre Stack is a pointer to the stack head structureDataOut contains a reference variable to receive the data
Post Data have been returned to calling algorithm
Return True if successful ; False if underflow
1. if (stack empty)
1 success = false
2. else
1 dataOut = stack->stackAry[stack->top]
2 stack->top = stack->top - 1
3 stack->count = stack->count - 1
4 success = true
3. Return success
End PopStack

4. Stack Top
Algorithm StackTop
Stack is a pointer to the stack headstructure
Data have been returned to calling algorithm
Return True if data returned ; False if underflow
1. if (stack->count zero)
1 success = false
1 dataOut = stack->stackAry[stack->top].data
2 success = true
3. return success
End StackTop

5. Empty Stack
Algorithm EmptyStack
Pre Stack is a pointer to the stack headstructure
Post Return stack status
Return Boolean; True: stack empty , False: stackcontain data
1. if (stack->count > 0)
1 result = false
2 else
1 result = true
3. return result
End EmptyStack

6. Full Stack
Algorithm Full
StackStack is a pointer to the stack
head structure
Post Return stack status
Return Boolean; True: stack full , False:
memory available
1. if (stack->count < result =" false" result =" true">

7. Stack Count
Algorithm StackCount
Pre Stack is a pointer to the stack headstructure
Post Return stack count
Return Integer count of number of elements in stack
1. return (stack->count)
End StackCount

8. Destroy Stack
Algorithm DestroyStack
Pre Stack is a pointer to the stack head structure
Post Head structure and array recycled
Return null pointer
1.if (stack no empty)
1 recycle (stack->stackAry)
2 recycle (stack)
2.return null pointer
End DestroyStack

การประยุกต์ใช้สแตก
การประยุกต์ใช้สแตก จะใช้ในงานด้าน ปฏิบัตการของเครื่องคอมพิวเตอร์ที่ขั้นตอนการทำงานต้องการเก็บข่าวสารอันดับแรกสุดไว้ใช้ หลังสุด เช่น การทำงานของโปรแกรมแปลภาษานำไปใช้ในเรื่องของการโปรแกรมที่เรียกใช้โปรแกรมย่อย การคำนวณนิพจน์ทาง คณิตศาสตร์ และรีเคอร์ชั่น (Recursion)

การทำงานของโปรแกรมที่มีโปรแกรมย่อย
การทำงานของโปรแกรมหลักที่เรียกใช้โปรแกรมย่อยและในแต่ละโปรแกรมย่อยก็มีการเรียกใช้โปรแกรมย่อยต่อไปอีก สแตกจะสามารถเขามาช่วยในการทำงาน คือ แต่ละจุดของโปรแกรมที่เรียกใช้โปรแกรมย่อยจะเก็บเลขที่ของค่ำสั่งถัดไปที่เครื่องต้องกลับมาทำงานไว้ในสแตก หลังจากเสร็จสิ้นการทำงานในโปรแกรมย่อยแล้วจะทำการ pop ค่าเลขที่คำสั่งออกมาจากสแตก เพื่อกลับไปทำงานที่คำสั่งต่อจากคำสั่งที่เรียกใช้โปรแกรมย่อย

แสดงโปรแกรมหลักที่มีการเรียกใช้โปรแกรมย่อย การคำนวณนิพจน์ทางคณิตศาสตร์ในการเขียนนิพจน์ทางคณิตศาสตร์เพื่อการคำนวณจะต้องคำนึงถึงลำดับความสำคัญของเครื่องหมายสำหรับการคำนวณด้วยโดยทั่วไปนิพจน์ทางคณิตศาสตร์สามารถเขียนได้ 3 รูปแบบ คือ
1. นิพจน์ Infix นิพจน์รูปแบบนี้ operatorจะอยู่ตรงกลางระหว่างตัวถูกดำเนินการ 2 ตัว
2. นิพจน์ Postfix นิพจน์รูปแบบนี้ จะต้องเขียนตัวถูกดำเนินการตัวที่ 1 และ 2 ก่อน แล้วตามด้วย operator 3. นิพจน์ Prefix นิพจน์รูปแบบนี้ จะต้องเขียน operatorก่อนแล้วตามด้วยตัวถูกดำเนินการตัวที่ 1 และ 2


ตัวอย่างนิพจน์คณิตศาสตร์ในรูปแบบต่าง ๆ
นิพจน์ Postfix นิพจน์ Prefix
AB+C- - +ABC
ABC*+DE/- - +A*BC/DE
AB*C+DE/- - +*ABC/DE

ในการเขียนโปรแกรมคอมพิวเตอร์ด้วยภาษาระดับสูงคำสูงที่เป็นนิพจน์ทางคณิตศาสตร์จะเขียนอยู่ในรูปแบบของนิพจน์ Infix การคำนวณคำนิพจน์ในรูปแบบนี้ ตัวแปลภาษาต้อง ทำการ ตรวจสอบนิพจน์จากซ้ายไปขวา เพื่อหาเครื่องหมาย ที่ต้องคำนวณก่อน จงจะเริ่มคำนวณให้ แล้วทำแบบนี้ซ้ำ ๆกันจนกว่าจะ คำนวณเครื่องหมายครบทุกตัวทำให้การ ทำงานช้าและไม่สะดวก ต่อการคำนวณการแก้ปัญหานี้ ตัวแปลภาษาจะทำงานแปลงนิพจน์ Infix ให้ อยู่ในรูปแบบที่ช่วยให้การคำนวณสะดวกและรวดเร็วขึ้น โดยแปลงให้อยู่ในรูปของนิพจน์ Postfix ในการแปลงจากนิพจน์ Infixไปเป็นนิพจน์ Postfixจะใช้เทคนิคของการจัดเก็บข้อมูลในโครงสร้างสแตกเขามาช่วย โดยพิจารณานิพจน์ Infix ที่ละตัวอักษรจากซ้ายไปขวา และย้าย ตัวอักษรเหล่านั้นไปเป็นนิพจน์ Postfixที่ละตัว ส่วนตัวดำเนินการหรือ operator จะถูกนำไปเก็บไว้ในสแตก


ค่าลำดับความสำคัญของตัวดำเนินการ
ขั้นตอนการแปลงจากนิพจน์ Infix เป็นนิพจน์
1. อ่านอักขระในนิพจน์ Infix เข้ามาที่ละตัว

2. ถ้าเป็นตัวถูกดำเนินการจะถูกย้ายไปเป็นตัวอักษรในนิพจน์ Postfix
3. ถ้าเป็นตัวดำเนินการ จะนำค่าลำดับความสำคัญของตัว ดำเนินการที่อ่านเข้ามาเทียบกับค่าลำดับความสำคัญของตัวดำเนินการที่อยู่บนสุดของสแตก
- ถามความสำคัญมากกว่า จะถูก push ลงในสแตก

- ถามความสำคัญน้อยกว่าหรือเท่ากัน จะต้อง pop ตัว ดำเนินการที่อยู่ในสแตกขณะนั้นไปเรียงต่อกับตัวอักษรในนิพจน์ Postfix
4.ตัวดำเนินการที่เป็นวงเล็บปิด “)” จะไม่ push ลงในสแตกแต่มีผลให้ตัวดำเนินการอื่น ๆ ถูก popออกจากสแตก นำไป เรียงต่อกันในนิพจน์ Postfix จนกว่าจะเจอ “(” จะ popวงเล็บเปิดออกจากสแตกแต่ไม่นำไปเรียงต่อ
5.เมื่อทำการอ่านตัวอักษรในนิพจน์ Infix หมดแล้ว ให้ทำการ Pop ตัวดำเนินการทุก ตัวในสแตกนำมาเรียงต่อในนิพจน์

ตัวอย่าง
การแปลงนิพจน์ Infix เป็นนิพจน์ Postfix นิพจน์ A-B/C+D*Eตัวที่อ่านเข้ามา ผลลัพธ์ในสแตก นิพจน์ Postfix
A ว่าง A
- - A
B - AB
/ -/ AB

C -/ ABC
+ + ABC/-
D + ABC/-D
* +* ABC/-D
E +* ABC/-DE
ABC/-DE*+
นิพจน์ A*(B+C-D)/E
ในการคำนวณค่า Postfix ที่แปลงมาแล้ว ตัวแปลภาษาจะทำการคำนวณโดยใช้โครงสร้างสแตกช่วยอีกเช่นกัน ขั้นตอนในการคำนวณ
1. อ่านตัวอักษรในนิพจน์ Postfix จากซ้ายไปขวาทีละ ตัวอักษร
2. ถ้าเป็นตัวถูกดำเนินการ ให้ทำการ push ตัวถูกดำเนินการ นั้นลงในสแตก แล้วกลับไปอ่านอักษรตัวใหม่เข้ามา
3. ถ้าเป็นตัวดำเนินการ ให้ทำการ pop ค่าจากสแตก 2 ค่า โดยตัวแรกเป็นตัวถูกดำเนินการตัวที่ 2 และตัวที่ 1ตามลำดับ
4. ทำการคำนวณ ตัวถูกดำเนินการตัวที่ 1ด้วยตัวถูกดำเนินการตัวที่ 2โดยใช้ตัวดำเนินการในข้อ 3
5. ทำการ push ผลลัพธท์ได้จากการคำนวณในข้อ 4 ลงสแตก
6. ถ้าตัวอักษรในนิพจน์ Postfix ยังอ่านไม่หมดให้กลับไปทำข้อ 1 ใหม่


Algorithm PostfixEvaluate
Pre a valid expression
Post postfix value computed
Return value of expression
1. exprSize= length of string
2. Stack = createStack
3. Index = 1
4. Loop (index<=exprSize) 1 if (expr[index] is operand 1 pushStack(stack,exp[index]) 1 popStack(stack, operand2) 2 popStack(stack, operand1) 3 operator = expr[index] 4 value = calculate (operand1, operator,

5 pushStack(stack,value)
3 index= index+1
5. popStack(stack,result)
6. destroyStack(stack)
7. return (result)
End PostfixEvaluate


ตัวอย่าง
ขั้นตอนการคำนวณจากนิพจน์ Postfix ABC+D-*E/



แบบฝึกหัด
1. อธิบายหลักการทำงานของ Stack
2. การแทนที่ของข้อมูลในสแตกมีกี่ประเภท อะไรบ้าง อธิบายพร้อมยกตัวอย่างประกอบ
3. การประยุกต์ใช้ สแตก Postfix ของ AB+CD*-E/ ใหอธิบายตามขั้นตอนการทำงาน
4. 15*A-F+D/J-(5*T)



ไม่มีความคิดเห็น:

แสดงความคิดเห็น