# Merge K Sorted Lists - C++ Implementation

A comprehensive C++ solution for merging k sorted linked lists into one sorted linked list, featuring multiple algorithmic approaches with detailed performance analysis.

## Features

- **Three Different Algorithms**:
  1. **Divide and Conquer** - O(N log k) time, O(log k) space
  2. **Priority Queue (Min-Heap)** - O(N log k) time, O(k) space  
  3. **Merge One by One** - O(k*N) time, O(1) space

- **Comprehensive Testing**: Edge cases, performance benchmarks, and demonstrations
- **Memory Management**: Proper cleanup and memory leak prevention
- **Modern C++**: Uses C++17 features and follows established coding standards
- **Professional Documentation**: Detailed comments and API documentation

## Problem Description

Given an array of k linked lists, where each linked list is sorted in ascending order, merge all the linked lists into one sorted linked list and return it.

### Example
```
Input: lists = [[1,4,5],[1,3,4],[2,6]]
Output: [1,1,2,3,4,4,5,6]
```

## Algorithm Approaches

### 1. Divide and Conquer (Recommended)
- **Time Complexity**: O(N log k) where N is total number of nodes
- **Space Complexity**: O(log k) for recursion stack
- **Best for**: Balanced performance and memory usage
- **How it works**: Recursively divides the list of k lists into pairs and merges them

### 2. Priority Queue (Min-Heap)
- **Time Complexity**: O(N log k)
- **Space Complexity**: O(k) for the priority queue
- **Best for**: When k is small relative to N
- **How it works**: Uses a min-heap to always extract the smallest element

### 3. Merge One by One
- **Time Complexity**: O(k*N) - less efficient for large k
- **Space Complexity**: O(1) - most memory efficient
- **Best for**: When memory is extremely limited
- **How it works**: Sequentially merges each list with the accumulated result

## File Structure

```
├── MergeKSortedLists.h     # Header file with class definitions
├── MergeKSortedLists.cc    # Implementation file
├── main.cc                 # Demo and testing program
├── Makefile               # Build configuration
└── README_MergeKSortedLists.md  # This documentation
```

## Building and Running

### Prerequisites
- C++17 compatible compiler (g++, clang++)
- Make utility

### Build Commands
```bash
# Build the program
make

# Build and run
make run

# Build debug version
make debug

# Build optimized release version
make release

# Clean build artifacts
make clean

# Show help
make help
```

### Manual Compilation
```bash
g++ -std=c++17 -Wall -Wextra -O2 MergeKSortedLists.cc main.cc -o merge_k_sorted_lists
./merge_k_sorted_lists
```

## Usage Example

```cpp
#include "MergeKSortedLists.h"

// Create test lists
std::vector<ListNode*> lists = {
    CreateList({1, 4, 5}),
    CreateList({1, 3, 4}),
    CreateList({2, 6})
};

// Create solver instance
MergeKSortedLists solver;

// Method 1: Divide and Conquer (recommended)
ListNode* result1 = solver.MergeKListsDivideConquer(lists);

// Method 2: Priority Queue
ListNode* result2 = solver.MergeKListsPriorityQueue(lists);

// Method 3: One by One
ListNode* result3 = solver.MergeKListsOneByOne(lists);

// Print results
PrintList(result1);  // Output: [1, 1, 2, 3, 4, 4, 5, 6]

// Clean up memory
DeleteList(result1);
DeleteList(result2);
DeleteList(result3);
```

## API Reference

### Core Classes

#### `ListNode`
Represents a node in a singly-linked list.
```cpp
struct ListNode {
    int mVal;           // Node value
    ListNode* mpNext;   // Pointer to next node
    
    ListNode();                              // Default constructor
    ListNode(int val);                       // Constructor with value
    ListNode(int val, ListNode* next);       // Constructor with value and next
};
```

#### `MergeKSortedLists`
Main solver class with three different merge algorithms.
```cpp
class MergeKSortedLists {
public:
    // Three different merge approaches
    ListNode* MergeKListsDivideConquer(std::vector<ListNode*>& lists);
    ListNode* MergeKListsPriorityQueue(std::vector<ListNode*>& lists);
    ListNode* MergeKListsOneByOne(std::vector<ListNode*>& lists);
};
```

### Utility Functions

```cpp
// Create linked list from vector
ListNode* CreateList(const std::vector<int>& values);

// Print linked list
void PrintList(ListNode* head);

// Delete linked list and free memory
void DeleteList(ListNode* head);
```

## Performance Analysis

The program includes built-in performance testing that compares all three approaches:

```
Testing with 10 lists, each with 100 elements
Divide and Conquer: 2 ms
Priority Queue: 3 ms
One by One: 15 ms
```

## Edge Cases Handled

- Empty input vector
- Single list in input
- Lists containing null pointers
- Lists of varying lengths
- Duplicate values across lists

## Memory Management

- All dynamically allocated memory is properly freed
- RAII principles followed where applicable
- No memory leaks in normal operation
- Exception-safe cleanup

## Code Style

This implementation follows the established C++ coding standards:
- Meaningful variable and function names with proper prefixes
- Clear class organization (public, protected, private)
- Comprehensive documentation with Doxygen-style comments
- Consistent naming conventions (mVariable for members, etc.)
- Proper const-correctness

## Testing

The program includes comprehensive testing:
- Basic functionality demonstration
- Edge case validation
- Performance benchmarking
- Memory leak verification

Run the program to see all tests in action:
```bash
make run
```

## License

This project is licensed under the Apache License 2.0. See the license headers in source files for details.

## Contributing

When contributing to this project:
1. Follow the established C++ coding standards
2. Add appropriate tests for new functionality
3. Update documentation as needed
4. Ensure no memory leaks are introduced
5. Maintain backward compatibility where possible