Skip to content
/ pqueue Public

A high-performance Go library that provides intelligent priority queue operations and adaptive sorting algorithms

License

Notifications You must be signed in to change notification settings

mew-sh/pqueue

Repository files navigation

PQueue - Intelligent Priority Queue and Sorting Library

Go Version GoDoc Go Report Card License

PQueue is a high-performance Go library that provides intelligent priority queue operations and adaptive sorting algorithms. It automatically selects the optimal sorting algorithm based on data characteristics, ensuring maximum performance across different scenarios.

Features

  • 🧠 Intelligent Algorithm Selection: Automatically chooses the best sorting algorithm based on data type, size, and patterns
  • 🚀 High Performance: Optimized implementations of multiple sorting algorithms
  • 🔧 Generic Support: Works with any comparable type using Go generics
  • 📊 Priority Queue Operations: Push, pop, peek operations with automatic ordering
  • 🎯 Multiple Data Types: Built-in support for integers, floats, strings, and custom types
  • 📈 Comprehensive Testing: Extensive test suite with benchmarks

Quick Start

package main

import (
    "fmt"
    "github.com/mew-sh/pqueue"
)

func main() {
    // Example as requested
    a := []int{6, 5, 4, 9, 2, 7, 1, 8}
    p := pqueue.NewInts(a)
    
    // Pop minimum element
    min, _ := p.Pop()
    fmt.Printf("Popped: %d\n", min) // Output: 1
    
    // Sort remaining elements
    p.Sort()
    fmt.Printf("Sorted: %v\n", p.ToSlice()) // Output: [2 4 5 6 7 8 9]
}

Supported Data Types

PQueue provides comprehensive support for all Go data types through intelligent type inference and optimized algorithms:

Basic Types

  • Integers: int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64
  • Floating Point: float32, float64
  • Strings: string
  • Byte Slices: []byte
  • Rune Slices: []rune

Complex Types

  • Slices: []T (slice of any type)
  • Arrays: [N]T (fixed-size arrays)
  • Structs: Custom struct types with comparison functions
  • Pointers: *T (with nil-safe comparisons)
  • Maps: map[K]V (with custom comparison logic)
  • Interfaces: Interface types
  • Channels: chan T
  • Functions: func types

Constructor Functions

// Basic types
intQueue := pqueue.NewInts([]int{3, 1, 4, 1, 5})
floatQueue := pqueue.NewFloats([]float64{3.14, 2.71, 1.41})
stringQueue := pqueue.NewStrings([]string{"zebra", "apple", "banana"})

// Complex types
byteQueue := pqueue.NewBytes([][]byte{[]byte("hello"), []byte("world")})
runeQueue := pqueue.NewRunes([][]rune{[]rune("世界"), []rune("hello")})

// Generic constructor for any type
customQueue := pqueue.New(data, func(a, b CustomType) bool {
    return a.Field < b.Field
})

// For comparable types
comparableQueue := pqueue.NewComparable(data, lessFunc)

Algorithm Selection Strategy

The library automatically selects the optimal algorithm based on data characteristics:

Scenario Optimization Algorithm Use Case
Very Small Arrays (≤16) Insertion Sort Minimal overhead for tiny datasets
Nearly Sorted Data Insertion Sort Exploits existing order
Small Integer Range Counting Sort Linear time for bounded integers
Large Integer Data Radix Sort Non-comparative sorting
Large General Data Introsort Hybrid approach with guaranteed O(n log n)
Real-world Data Timsort Adaptive to real-world patterns
Distributed/Parallel Merge Sort Stable and parallelizable

API Reference

Creating Priority Queues

// For integers
pq := pqueue.NewInts([]int{3, 1, 4, 1, 5})

// For floats
pq := pqueue.NewFloats([]float64{3.14, 2.71, 1.41})

// For strings
pq := pqueue.NewStrings([]string{"apple", "banana", "cherry"})

// For custom types with custom comparison
pq := pqueue.New(data, func(a, b MyType) bool { return a.Value < b.Value })

Basic Operations

// Priority Queue Operations
size := pq.Size()           // Get number of elements
isEmpty := pq.IsEmpty()     // Check if empty
pq.Push(item)              // Add element
item, err := pq.Pop()      // Remove and return minimum
item, err := pq.Peek()     // Get minimum without removing

// Sorting Operations
pq.Sort()                                    // Auto-select best algorithm
pq.SortWithStrategy(pqueue.QuickStrategy)    // Use specific algorithm
data := pq.ToSlice()                        // Get sorted copy

Available Sorting Strategies

type SortStrategy int

const (
    AutoStrategy      // Automatic selection (default)
    RadixStrategy     // Radix sort (integers only)
    CountingStrategy  // Counting sort (small range integers)
    InsertionStrategy // Insertion sort (small/nearly sorted data)
    TimsortStrategy   // Timsort (adaptive merge sort)
    IntrosortStrategy // Introsort (quick + heap + insertion)
    MergeStrategy     // Merge sort (stable, parallelizable)
    QuickStrategy     // Quick sort (general purpose)
)

Performance Examples

Automatic Algorithm Selection

// Small data → Insertion Sort
smallData := []int{3, 1, 4, 1, 5}
pq := pqueue.NewInts(smallData)
pq.Sort() // Uses insertion sort automatically

// Nearly sorted → Insertion Sort  
nearlySorted := []int{1, 2, 3, 5, 4, 6, 7}
pq2 := pqueue.NewInts(nearlySorted)
pq2.Sort() // Detects pattern, uses insertion sort

// Large dataset → Introsort
largeData := make([]int, 10000)
// ... populate with random data
pq3 := pqueue.NewInts(largeData)
pq3.Sort() // Uses introsort for guaranteed performance

Specific Algorithm Usage

data := []int{170, 45, 75, 90, 2, 802, 24, 66}
pq := pqueue.NewInts(data)

// Force specific algorithms
pq.SortWithStrategy(pqueue.RadixStrategy)     // Good for integers
pq.SortWithStrategy(pqueue.MergeStrategy)     // Stable sort
pq.SortWithStrategy(pqueue.CountingStrategy)  // Small range integers

Benchmarks

Performance comparison on 5000 random integers:

Auto Selection:    245.2µs
Quick Sort:        312.8µs  
Merge Sort:        387.1µs
Introsort:        251.4µs
Timsort:          298.7µs

Auto selection chooses the optimal algorithm, often outperforming manual selection.

Installation

go mod init your-project
go get github.com/mew-sh/pqueue

Advanced Usage

Custom Types

type Person struct {
    Name string
    Age  int
}

people := []Person{
    {"Alice", 30},
    {"Bob", 25},
    {"Charlie", 35},
}

// Sort by age
pq := pqueue.New(people, func(a, b Person) bool {
    return a.Age < b.Age
})

pq.Sort()
sorted := pq.ToSlice() // Sorted by age

Multiple Criteria Sorting

// Sort by multiple criteria
pq := pqueue.New(people, func(a, b Person) bool {
    if a.Age == b.Age {
        return a.Name < b.Name
    }
    return a.Age < b.Age
})

Testing

Run the comprehensive test suite:

go test ./...                    # Run all tests
go test -bench=.                # Run benchmarks
go test -v                      # Verbose output
go test -race                   # Race condition detection

Examples

See the example directory for comprehensive usage examples including:

  • Basic priority queue operations
  • Automatic algorithm selection
  • Performance comparisons
  • Different data types
  • Custom comparison functions

Run the example:

go run example/main.go

Data Type Examples

// 1. Numeric Types
integers := []int{6, 5, 4, 9, 2, 7, 1, 8}
intQueue := pqueue.NewInts(integers)
intQueue.Sort()
fmt.Println(intQueue.ToSlice()) // [1 2 4 5 6 7 8 9]

floats := []float64{3.14, 2.71, 1.41, 1.73}
floatQueue := pqueue.NewFloats(floats)
floatQueue.Sort()
fmt.Println(floatQueue.ToSlice()) // [1.41 1.73 2.71 3.14]

// 2. String Types
strings := []string{"zebra", "apple", "banana"}
stringQueue := pqueue.NewStrings(strings)
stringQueue.Sort()
fmt.Println(stringQueue.ToSlice()) // [apple banana zebra]

// Unicode strings with runes
words := [][]rune{[]rune("世界"), []rune("hello"), []rune("αβγ")}
runeQueue := pqueue.NewRunes(words)
runeQueue.Sort()

// Byte slices
byteSlices := [][]byte{[]byte("zebra"), []byte("apple")}
byteQueue := pqueue.NewBytes(byteSlices)
byteQueue.Sort()

// 3. Custom Struct Types
type Person struct {
    Name string
    Age  int
}

people := []Person{
    {Name: "Alice", Age: 30},
    {Name: "Bob", Age: 25},
    {Name: "Charlie", Age: 35},
}

// Sort by age, then by name
personQueue := pqueue.New(people, func(a, b Person) bool {
    if a.Age != b.Age {
        return a.Age < b.Age
    }
    return a.Name < b.Name
})
personQueue.Sort()

// 4. Pointer Types
values := []int{5, 2, 8, 1, 9}
ptrs := make([]*int, len(values))
for i := range values {
    ptrs[i] = &values[i]
}

ptrQueue := pqueue.New(ptrs, func(a, b *int) bool {
    if a == nil || b == nil {
        return a == nil && b != nil // nil values first
    }
    return *a < *b
})
ptrQueue.Sort()

// 5. Slice Types (2D arrays)
slicesOfInts := [][]int{
    {3, 2, 1},
    {1, 2, 3},
    {2, 1, 3},
}

sliceQueue := pqueue.New(slicesOfInts, func(a, b []int) bool {
    // Custom comparison: by sum, then lexicographically
    sumA, sumB := sum(a), sum(b)
    if sumA != sumB {
        return sumA < sumB
    }
    for i := 0; i < len(a) && i < len(b); i++ {
        if a[i] != b[i] {
            return a[i] < b[i]
        }
    }
    return len(a) < len(b)
})
sliceQueue.Sort()

// 6. Interface Types
type Comparable interface {
    CompareTo(other interface{}) int
}

// For types implementing Comparable interface
comparableQueue := pqueue.NewWithComparable([]ComparableType{...})

Algorithm Details

Insertion Sort

  • Best Case: O(n) for nearly sorted data
  • Average/Worst: O(n²)
  • Use: Small arrays (≤16 elements), nearly sorted data

Quick Sort

  • Average: O(n log n)
  • Worst: O(n²)
  • Use: General purpose, good cache performance

Merge Sort

  • All Cases: O(n log n)
  • Use: Stable sorting, parallel processing
  • Space: O(n)

Introsort

  • All Cases: O(n log n) guaranteed
  • Use: Large datasets, unknown data patterns
  • Features: Hybrid of quicksort, heapsort, and insertion sort

Timsort

  • Best: O(n) for real-world data
  • Average/Worst: O(n log n)
  • Use: Real-world data with existing patterns

Radix Sort

  • Complexity: O(d × n) where d is number of digits
  • Use: Integers, strings with fixed-length keys
  • Space: O(n + k)

Counting Sort

  • Complexity: O(n + k) where k is range
  • Use: Small range integers
  • Space: O(k)

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • Inspired by the intelligent sorting strategies used in production systems
  • Algorithm implementations based on proven computer science research
  • Performance optimizations derived from real-world usage patterns

About

A high-performance Go library that provides intelligent priority queue operations and adaptive sorting algorithms

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages