การดู : 0

12/04/2026 18:16น.

JS2GO EP.34 การจัดการ Heap และ Priority Queue ใน Go และ JavaScript

JS2GO EP.34 การจัดการ Heap และ Priority Queue ใน Go และ JavaScript

#Heap

#Priority Queue

#Go

#JavaScript

#JS2GO

เมื่อระบบของคุณต้องจัดลำดับการทำงานของ task เช่น Job Queue, Pathfinding (A*), หรือ Recommendation Engine คุณจำเป็นต้องมีโครงสร้างข้อมูลที่สามารถ “เลือกข้อมูลที่สำคัญที่สุดก่อน” ได้อย่างมีประสิทธิภาพ และนั่นคือเหตุผลที่ Heap และ Priority Queue เข้ามามีบทบาทสำคัญในโลกของการพัฒนาโปรแกรม

 

ในบทความนี้ เราจะอธิบายหลักการทำงานของ Heap และ Priority Queue พร้อม ตัวอย่างโค้ดจริงทั้งใน JavaScript และ Go
รวมถึง แนวทางปฏิบัติ (Best Practices) สำหรับใช้งานในระบบจริง 🚀

 

1. ทำความเข้าใจกับ Heap

 

Heap คือโครงสร้างข้อมูลแบบ Tree ที่ใช้ในการจัดลำดับข้อมูลตาม “ลำดับความสำคัญ” (priority)
โดยทั่วไปแบ่งออกเป็น 2 ประเภทหลัก:

  • Min-Heap: ค่าที่เล็กที่สุดจะอยู่บนสุดของโครงสร้าง
  • Max-Heap: ค่าที่ใหญ่ที่สุดจะอยู่บนสุดของโครงสร้าง

 

Heap ถูกใช้อย่างแพร่หลายในระบบที่ต้องการ Priority Scheduling, Shortest Path (Dijkstra), หรือ Task Queue ที่ต้องเลือก task สำคัญก่อนเสมอ

 

2. การใช้งาน Heap ใน JavaScript

 

JavaScript ไม่มี Heap เป็น built-in data structure แต่สามารถสร้างขึ้นเองได้ง่าย ๆ ด้วย class หรือใช้ library เช่น heap-js

 

🔹 ตัวอย่าง: การสร้าง Min-Heap ด้วย JavaScript

class MinHeap {
  constructor() {
    this.heap = [];
  }

  getParentIndex(i) { return Math.floor((i - 1) / 2); }
  getLeftChildIndex(i) { return 2 * i + 1; }
  getRightChildIndex(i) { return 2 * i + 2; }

  swap(i1, i2) {
    [this.heap[i1], this.heap[i2]] = [this.heap[i2], this.heap[i1]];
  }

  insert(value) {
    this.heap.push(value);
    this.heapifyUp();
  }

  heapifyUp() {
    let index = this.heap.length - 1;
    while (this.getParentIndex(index) >= 0 &&
           this.heap[this.getParentIndex(index)] > this.heap[index]) {
      this.swap(index, this.getParentIndex(index));
      index = this.getParentIndex(index);
    }
  }

  extractMin() {
    if (this.heap.length === 0) return null;
    if (this.heap.length === 1) return this.heap.pop();

    const root = this.heap[0];
    this.heap[0] = this.heap.pop();
    this.heapifyDown(0);
    return root;
  }

  heapifyDown(index) {
    let smallest = index;
    const left = this.getLeftChildIndex(index);
    const right = this.getRightChildIndex(index);

    if (left < this.heap.length && this.heap[left] < this.heap[smallest]) smallest = left;
    if (right < this.heap.length && this.heap[right] < this.heap[smallest]) smallest = right;

    if (smallest !== index) {
      this.swap(index, smallest);
      this.heapifyDown(smallest);
    }
  }
}

// ทดสอบการใช้งาน
const minHeap = new MinHeap();
minHeap.insert(5);
minHeap.insert(2);
minHeap.insert(8);
minHeap.insert(1);

console.log(minHeap.extractMin()); // 1
console.log(minHeap.extractMin()); // 2

 

ผลลัพธ์:

1
2

 

ข้อดี:
✅ เข้าใจง่ายและสามารถ customize ได้
✅ เหมาะสำหรับฝึกอัลกอริทึม หรือใช้ในระบบ simulation

 

ข้อจำกัด:
❌ ต้อง implement เอง
❌ ไม่มี type safety

 

3. การใช้งาน Heap และ Priority Queue ใน Go

 

ภาษา Go มี package มาตรฐานชื่อ container/heap ที่ช่วยให้เราสามารถจัดการ heap ได้โดยตรงและปลอดภัยด้วย type checking

 

🔹 ตัวอย่าง: การสร้าง Priority Queue ใน Go

package main

import (
	"container/heap"
	"fmt"
)

// Item แทน task ที่มี priority
type Item struct {
	value    string
	priority int
	index    int
}

// PriorityQueue คือ heap ของ Item
type PriorityQueue []*Item

func (pq PriorityQueue) Len() int { return len(pq) }
func (pq PriorityQueue) Less(i, j int) bool {
	return pq[i].priority < pq[j].priority // Min-Heap
}
func (pq PriorityQueue) Swap(i, j int) {
	pq[i], pq[j] = pq[j], pq[i]
	pq[i].index = i
	pq[j].index = j
}
func (pq *PriorityQueue) Push(x any) {
	item := x.(*Item)
	item.index = len(*pq)
	*pq = append(*pq, item)
}
func (pq *PriorityQueue) Pop() any {
	old := *pq
	n := len(old)
	item := old[n-1]
	*pq = old[0 : n-1]
	return item
}

func main() {
	pq := make(PriorityQueue, 0)
	heap.Init(&pq)

	heap.Push(&pq, &Item{value: "Job A", priority: 3})
	heap.Push(&pq, &Item{value: "Job B", priority: 1})
	heap.Push(&pq, &Item{value: "Job C", priority: 2})

	for pq.Len() > 0 {
		item := heap.Pop(&pq).(*Item)
		fmt.Printf("%s (priority %d)\n", item.value, item.priority)
	}
}

 

ผลลัพธ์:

Job B (priority 1)
Job C (priority 2)
Job A (priority 3)

 

ข้อดีของ Go:
✅ มี heap package ให้ใช้งานได้ทันที
✅ Type-safe และมีประสิทธิภาพสูง
✅ เหมาะกับระบบ production เช่น job queue, scheduler, และ background worker

 

4. แนวทางปฏิบัติที่เหมาะสม (Best Practices)

 

Use Caseเหมาะกับภาษาคำแนะนำ
Algorithm SimulationJavaScriptเขียน heap เองเพื่อฝึกเข้าใจอัลกอริทึมพื้นฐาน
Production Queue SystemGoใช้ container/heap เพื่อประสิทธิภาพสูงสุด
Pathfinding (A*, Dijkstra)ทั้งสองภาษาใช้ Priority Queue เพื่อหาทางที่สั้นที่สุด
Task Scheduling / Job ManagementGoใช้ Priority Queue เพื่อควบคุมลำดับงานอย่างมีประสิทธิภาพ

 

5. สรุปเปรียบเทียบ Heap และ Priority Queue

 

คุณสมบัติJavaScriptGo
Built-in Support❌ ไม่มี✅ มี (container/heap)
Type Safety❌ ไม่มี✅ มี
Performanceปานกลางสูงมาก
Suitable Forฝึก algorithm, simulationระบบจริง, job scheduling
Ease of Useเข้าใจง่ายต้อง implement interface

 


 

สรุปท้ายบท

 

การเข้าใจการทำงานของ Heap และ Priority Queue จะช่วยให้คุณสามารถสร้างระบบที่จัดลำดับความสำคัญของงานได้อย่างมีประสิทธิภาพ ไม่ว่าจะเป็น Job Queue, Pathfinding Engine, หรือ Task Manager

  • 💡 ถ้าคุณต้องการ “ความยืดหยุ่นและเข้าใจพื้นฐานอัลกอริทึม” → ใช้ JavaScript
  • ⚙️ ถ้าคุณต้องการ “ประสิทธิภาพระดับ Production และระบบคิวที่แข็งแรง” → ใช้ Go

 

ตอนต่อไป

 

ใน EP.35 ของซีรีส์ JS2GO เราจะพาคุณไปเรียนรู้เรื่อง Sorting Algorithms ทั้งใน JavaScript และ Go เพื่อเปรียบเทียบวิธีการจัดเรียงข้อมูล เช่น Bubble Sort, Merge Sort, Quick Sort, และการใช้งาน Go’s sort package ว่าภาษาไหนทำได้เร็วกว่ากัน และเทคนิคไหนเหมาะกับระบบของคุณมากที่สุด 🔥

 

อ่านบทความ Series อื่นๆ

🔵 Facebook: https://www.facebook.com/superdev.academy.th

🔴 YouTube : Superdev Academy

📸 Instagram: Superdev Academy

🎬 TikTok: https://www.tiktok.com/@superdevacademy?lang=th-TH

🌐 Website: https://www.superdevacademy.com/