Choose the last item as a pivot, partition smaller values to its left, then recurse on the two sides.

Algorithm

Basic Implementation

basic.cs
using System;

class Program {
	static void Main() {
		int[] arr = new int[] { 4, 1, 5, 2, 3 };
		QuickSort(arr, 0, arr.Length - 1);
		PrintArray(arr);
	}

	static void PrintArray(int[] arr) {
		Console.Write("[");
		for (int i = 0; i < arr.Length; i++) {
			if (i > 0) Console.Write(", ");
			Console.Write(arr[i]);
		}
		Console.WriteLine("]");
	}
	static int Partition(int[] arr, int low, int high) {
		int pivot = arr[high];
		int i = low - 1;
		for (int j = low; j < high; j++) {
			if (arr[j] <= pivot) {
				i++;
				int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp;
			}
		}
		int swap = arr[i + 1]; arr[i + 1] = arr[high]; arr[high] = swap;
		return i + 1;
	}

	static void QuickSort(int[] arr, int low, int high) {
		if (low < high) {
			int pivotIndex = Partition(arr, low, high);
			QuickSort(arr, low, pivotIndex - 1);
			QuickSort(arr, pivotIndex + 1, high);
		}
	}
}

The pinned first partition uses [4, 1, 5, 2, 3] with pivot 3. The diagrams track the boundary, swaps, and recursive ranges.

Step 1 - Choose the last value as pivot

The pivot is arr[4] = 3, and i starts just before the current range.

Initial partition state for [4, 1, 5, 2, 3].i0i1i2i3i441523j startspivot

Step 2 - Swap small values left

1 and 2 are <= pivot, so they move into the left partition.

After scanning values before the pivot: [1, 2, 5, 4, 3].i0i1i2i3i412543<= 3<= 3> 3> 3pivot

Step 3 - Place pivot, then recurse

Swapping pivot 3 into index 2 gives [1, 2, 3, 4, 5]; recurse on [1, 2] and [4, 5].

Pivot lands at index 2 and splits the remaining work.left rangepivotright range[1, 2]3 at i2[4, 5]quick_sort(0,1)fixedquick_sort(3,4)

Complexity

  • Time: O(n^2) worst, O(n log n) average
  • Space: O(log n) average call stack
  • Stable: no

Implementation notes

  • Keep the explicit algorithmic steps instead of calling a standard-library Array.Sort. This checked-in replay shows each comparison and swap in the first partition, then summarizes the recursive calls on already-sorted sides.
  • The int[] is a managed reference type, so swaps mutate the same array object without pointer arithmetic or manual free/GC control. Index bounds are still enforced at runtime, which keeps the partition indices visible during the replay instead of relying on unchecked pointer movement.
pivot The final element is moved to the boundary between smaller and larger values.
partition One scan rearranges the current range before the recursive calls.