Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 140 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# CLAUDE.md — Sorting Algorithm Project

## Project Overview

This is a C++ academic project (ECE 4050 / CSC 5050 - Project 3) that implements and compares four classic sorting algorithms across three STL container types (`vector`, `list`, `set`). It tracks operation counts (accesses and comparisons) to measure and compare algorithm efficiency.

---

## Repository Structure

```
Sorting-Algorithm/
├── main.cpp # Top-level entry point (root copy)
├── sorting.cpp # All sorting algorithm implementations (root copy)
├── sort.h # Central header: SortMetrics struct + all function declarations
├── random.h / random.cpp # Random data generation utilities
├── operators.h / operators.cpp # Stream insertion operator overloads for STL containers
├── sort_metrics.cpp # Stream insertion operator for SortMetrics
├── sort/ # MSVC Debug build artifacts (compiled object files, logs)
├── sorting/ # Visual Studio project folder (canonical source of truth)
│ ├── main.cpp # Entry point (duplicate of root main.cpp)
│ ├── sorting.cpp # Algorithm implementations (duplicate of root sorting.cpp)
│ ├── sort.h # Header (duplicate of root sort.h)
│ ├── random.h / random.cpp
│ ├── operators.h / operators.cpp
│ ├── sort_metrics.cpp
│ ├── sorting.sln # Visual Studio solution file
│ ├── sorting.vcxproj # Visual Studio project file
│ └── Debug/ # MSVC build output (sorting.exe, .obj files, .pdb)
└── README.md
```

> **Note:** Source files exist in both the repository root and under `sorting/`. The `sorting/` directory is the Visual Studio project and contains the compiled executable (`sorting/Debug/sorting.exe`). The root-level `.cpp`/`.h` files appear to be duplicates uploaded alongside the VS project.

---

## Source File Roles

| File | Purpose |
|---|---|
| `sort.h` | Declares `SortMetrics` struct and all sort function signatures |
| `sorting.cpp` | Implements all sort algorithms and helper functions |
| `main.cpp` | Driver: generates random data, calls each sort, prints results |
| `random.cpp` | `random_vector(n)`, `vector_to_list()`, `vector_to_set()` |
| `operators.cpp` | `operator<<` overloads for `vector<int>`, `list<int>`, `set<int>` |
| `sort_metrics.cpp` | `operator<<` overload for `SortMetrics` |

---

## Key Data Structures

### `SortMetrics` (defined in `sort.h`)
```cpp
struct SortMetrics {
int accesses{ 0 }; // Count of array element accesses
int comparisons{ 0 }; // Count of element comparisons
};
```
Every sort function resets both fields to `0` at entry, then increments them during execution. This enables post-sort efficiency analysis.

---

## Implemented Algorithms

All sort functions have the signature `bool func(..., SortMetrics& metrics)` and return `true` on success, `false` on error (or stub `0`).

### Bubble Sort (`bubble_sort`)
- **`vector<int>`**: Standard optimized bubble sort using swap-flag early exit. Uses arithmetic swap (no `std::swap` or temp variable).
- **`list<int>`**: Selection-sort-style nested iterator loop (note: not a true bubble sort).
- **`set<int>`**: **Stub** — returns `0`, no implementation (sets are always ordered by invariant).

### Insertion Sort (`insertion_sort`)
- **`vector<int>`**: Standard insertion sort with key-based shifting.
- **`list<int>`**: **Not implemented** (commented out in header and main).
- **`set<int>`**: **Stub** — returns `0`.

### Merge Sort (`merge_sort`)
- **`vector<int>`**: Recursive merge sort. Uses two internal helpers:
- `mergeSort(vector, metrics)` — recursive splitter
- `merge(left, right, metrics)` — merge step using `erase`/`push_back`
- **`list<int>`**: **Not implemented**.
- **`set<int>`**: **Stub** — returns `0`.

### Quicksort (`quicksort`)
- **`vector<int>`**: In-place quicksort with middle-element pivot. Signature requires explicit `left` and `right` indices: `quicksort(vec, metrics, 0, n-1)`.
- **`list<int>`**: **Not implemented**.
- **`set<int>`**: **Stub** — returns `0`.

---

## Known Issues and Incomplete Implementations

- **`set<int>` stubs**: `bubble_sort(set)`, `insertion_sort(set)`, `merge_sort(set)`, and `quicksort(set)` all return `0` with no logic. `std::set` maintains sorted order automatically, so sorting is a no-op — these stubs exist to satisfy the interface.
- **`list<int>` for insertion/merge/quicksort**: Commented out in `sort.h` and `main.cpp`. A partial pseudocode stub exists in `sorting.cpp` (lines 98–111).
- **Metrics reset inside quicksort**: Quicksort resets `metrics.accesses` and `metrics.comparisons` to `0` at the start of each recursive call, meaning the final reported metrics only reflect the last recursive frame, not the total operation count.
- **Quicksort swaps indices, not values**: `swap(i, j)` swaps the index variables, not `vec[i]` and `vec[j]`. This is a bug — it should be `swap(vec[i], vec[j])`.

---

## Build System

The project targets **Visual Studio 2019** (MSVC v142 toolchain) on Windows. Build artifacts are in `sorting/Debug/`.

### Building on Linux (g++)
There is no Makefile. To compile manually:
```bash
g++ -std=c++17 -o sorting main.cpp sorting.cpp random.cpp operators.cpp sort_metrics.cpp
./sorting
```

All source files must be compiled together in a single translation unit group since they share declarations via headers but have no separate library setup.

---

## Conventions

- **`using namespace std;`** is used globally (declared at the top of `sort.h` and each `.cpp`).
- Headers use `#pragma once` for include guards.
- All functions that take a container take it by reference (`&`).
- `SortMetrics` is always passed by reference and reset at the start of each sort call.
- Internal/helper functions (`merge`, `mergeSort`) are defined in `sorting.cpp` but not declared in any header — they are file-scoped.
- The dataset size `n` is hardcoded to `10` in `main.cpp`. Change this value directly to test different sizes.

---

## Development Workflow

1. Edit source files (prefer files under `sorting/` as the VS project root).
2. Build with Visual Studio on Windows, or `g++` on Linux (see above).
3. Run the executable: `sorting/Debug/sorting.exe` (Windows) or `./sorting` (Linux).
4. Output shows the container contents before and after each sort, followed by `SortMetrics`.

---

## What NOT to Change Without Care

- **`sort.h` function signatures**: All implementations in `sorting.cpp` must match exactly. Adding or removing parameters breaks compilation.
- **`SortMetrics` struct fields**: `main.cpp` and `sort_metrics.cpp` depend on `accesses` and `comparisons` by name.
- **`operator<<` overloads in `operators.cpp`**: Used implicitly by `std::cout << vect` in `main.cpp`. Removing them breaks output.
- **Root-level source files vs `sorting/`**: Keep both in sync if edits are made, or consolidate to one location.
95 changes: 51 additions & 44 deletions sorting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,9 @@ bool bubble_sort(vector<int>& vec, SortMetrics& metrics) {
metrics.comparisons++; //if

if (vec[i] > vec[i + 1]) {
metrics.accesses += 3;
//vec[i] being accessed two extra times and vec[i+1] one extra time
//swap
vec[i] += vec[i + 1];
vec[i + 1] = vec[i] - vec[i + 1];
vec[i] -= vec[i + 1];
metrics.accesses += 2;
//two writes: vec[i] and vec[i+1] (reads already counted above)
swap(vec[i], vec[i + 1]);

swap_ = true;
}
Expand All @@ -42,24 +39,24 @@ bool bubble_sort(list<int>& list, SortMetrics& metrics) {
metrics.accesses = 0;
metrics.comparisons = 0;

for (auto i = begin(list); i != end(list); i++)
{
auto key = begin(list); //setting the new first element of the list
metrics.accesses++;
bool swapped = true;
while (swapped) {
swapped = false;
for (auto it = begin(list); it != end(list); ++it) {
auto next = std::next(it);
if (next == end(list)) break;

metrics.accesses += 2; //read *it and *next
metrics.comparisons++;

for (auto itr = key; itr != end(list); itr++)
{
metrics.accesses += 2; //i and itr
metrics.comparisons++ ;
if (*i < *(itr))
{
int temp = *i;
*i = *itr;
*itr = temp;
if (*it > *next) {
swap(*it, *next);
metrics.accesses += 2; //two writes for the swap
swapped = true;
}
}
}
return 0;
return true;
}

//Bubble sort with set
Expand All @@ -75,18 +72,19 @@ bool insertion_sort(vector<int>& vec, SortMetrics& metrics) {
metrics.comparisons = 0;

for (size_t j = 1; j < vec.size(); j++) {
metrics.accesses++; //vec[j]
metrics.accesses++; //read vec[j]
int key = vec[j];
int i = j - 1;

metrics.accesses += 2; //vec[i] and vec[i+1]
metrics.comparisons++;//vec[i] and key(=vec[j])
int i = (int)j - 1;

while (i >= 0 && vec[i] > key) {
while (i >= 0) {
metrics.accesses++; //read vec[i]
metrics.comparisons++; //compare vec[i] > key (counted whether true or false)
if (vec[i] <= key) break;
metrics.accesses++; //write vec[i+1]
vec[i + 1] = vec[i];
i--;
}
metrics.accesses++; //vec[i+1]
metrics.accesses++; //write vec[i+1] = key
vec[i + 1] = key;
}

Expand Down Expand Up @@ -126,14 +124,15 @@ vector<int> merge(vector<int> l, vector<int> r,SortMetrics& metrics) {

while (l.size() > 0 || r.size() > 0) {
if (l.size() > 0 && r.size() > 0) {
metrics.comparisons++;
metrics.accesses += 2; //read l[0] and r[0] for comparison
if (l.at(0) <= r.at(0)) {
metrics.comparisons++;
metrics.accesses += 2; //accessing and comparing the first elements in both halves
metrics.accesses++; //read l[0] for push_back
re.push_back(l.at(0)); //organizing the vector behind the smallest element in the portion
l.erase(l.begin()); //resseting the vector to use push_back again
l.erase(l.begin()); //resetting the vector to use push_back again
}
else {
metrics.accesses++; //accessing the element in r
metrics.accesses++; //read r[0] for push_back
re.push_back(r.at(0));
r.erase(r.begin());
}
Expand Down Expand Up @@ -183,6 +182,8 @@ vector<int> mergeSort(vector<int> vec, SortMetrics& metrics) {
}

bool merge_sort(vector<int>& vec, SortMetrics& metrics) {
metrics.accesses = 0;
metrics.comparisons = 0;
vec = mergeSort(vec, metrics); //recursively sorting the vector by calling the sorting function which uses the helper function to sort the vector

return 1;
Expand All @@ -198,45 +199,51 @@ bool merge_sort(set<int>& set, SortMetrics& metrics){
}

//quicksort with vectors
bool quicksort(vector<int>& vec, SortMetrics& metrics, int left, int right) {
metrics.accesses = 0;
metrics.comparisons = 0;

// Internal recursive helper — metrics are NOT reset here so totals accumulate
static void quicksort_helper(vector<int>& vec, SortMetrics& metrics, int left, int right) {
int i, j, mid, pivot;
i = left; // left partition of the vector
j = right; //right partition of the vector
mid = left + (right - left) / 2;
//pivot (chosen by using the middle element of the vector)
mid = left + (right - left) / 2;
//pivot (chosen by using the middle element of the vector)
pivot = vec[mid];
metrics.accesses++; //acccessing the vector element at mid
metrics.accesses++; //accessing the vector element at mid

while (j > left || i < right) {
metrics.comparisons += 2; //vector elements at i and j being compared with the pivot

while (vec[i] < pivot) {
metrics.accesses++;
i++; //incrementing i to find the element larger than the pivot
}
while (vec[j] > pivot) {
metrics.accesses++;
j--; //decrementing j to find the element smaller than the pivot
}
}

if (i <= j) {
swap(i, j); //with the two elements found from the while loops above, if i side elements is smaller than the j side elements, swtich. if not, no action taken as they are already in the right order
swap(vec[i], vec[j]); //swap the actual elements, not the indices
metrics.accesses += 2; //two writes for the swap
i++;
j--;
}
else {
// right side is larger
if (i < right)
quicksort(vec, metrics, i, right);
quicksort_helper(vec, metrics, i, right);
// left is larger
if (j > left)
quicksort(vec, metrics, left, j);
return 1;
quicksort_helper(vec, metrics, left, j);
return;
}
}
}

// Public entry point — resets metrics once, then delegates to helper
bool quicksort(vector<int>& vec, SortMetrics& metrics, int left, int right) {
metrics.accesses = 0;
metrics.comparisons = 0;
quicksort_helper(vec, metrics, left, right);
return 1;
}

Expand Down
Loading