Program to Sort a List of Numbers in Ascending Order: Complete Python Sorting Algorithm Implementation Guide

Program to sort a list of numbers in ascending order

Sorting is one of those problems every programmer eventually implements from scratch at least once, and then almost never implements from scratch again — because once I understood how Python’s built-in sorting actually works, I realized it’s almost always the better choice over hand-rolled sorting logic. In this guide, I’ll walk through both approaches: using Python’s built-in sorting tools the right way, and implementing a couple of classic sorting algorithms manually to understand what’s actually happening underneath, including their time complexity.

Reading a List of Numbers from the User

Before sorting anything, I need to get the numbers into a list. Here’s the pattern I use most often:

numbers_input = input("Enter numbers separated by spaces: ")
numbers = [int(n) for n in numbers_input.split()]
print("Original list:", numbers)

Example run:

Enter numbers separated by spaces: 9 3 7 1 5
Original list: [9, 3, 7, 1, 5]

.split() breaks the input string into individual pieces on whitespace, and the list comprehension converts each piece into an integer.

Method 1: Using Python’s Built-in sorted() Function

This is the approach I use in almost all real-world code, because it’s fast, well-tested, and requires no manual implementation:

numbers = [9, 3, 7, 1, 5]
sorted_numbers = sorted(numbers)
print("Ascending order:", sorted_numbers)
print("Original list unchanged:", numbers)

Output:

Ascending order: [1, 3, 5, 7, 9]
Original list unchanged: [9, 3, 7, 1, 5]

sorted() is a built-in function that returns a new sorted list, leaving the original untouched. This is important — if I want to sort a list in place instead, without creating a new one, I use the list’s own .sort() method:

numbers = [9, 3, 7, 1, 5]
numbers.sort()
print("Sorted in place:", numbers)

Output:

Sorted in place: [1, 3, 5, 7, 9]

Both sorted() and .sort() accept a reverse=True argument if I want descending order instead:

numbers = [9, 3, 7, 1, 5]
print(sorted(numbers, reverse=True))
# Output: [9, 7, 5, 3, 1]

A Complete Interactive Sorting Program

def sort_numbers():
    numbers_input = input("Enter numbers separated by spaces: ")
    try:
        numbers = [int(n) for n in numbers_input.split()]
    except ValueError:
        print("Please enter valid whole numbers only.")
        return

    ascending = sorted(numbers)
    print("Numbers in ascending order:", ascending)

sort_numbers()

Example run:

Enter numbers separated by spaces: 42 8 15 4 23 16
Numbers in ascending order: [4, 8, 15, 16, 23, 42]

How Python’s Built-in Sort Actually Works Internally

Python’s sorted() and .sort() both use an algorithm called Timsort, developed by Tim Peters specifically for Python (and later adopted by other languages, including Java for object arrays). Timsort is a hybrid sorting algorithm derived from merge sort and insertion sort, specifically designed to perform extremely well on real-world data, which is often partially ordered rather than completely random.

Key facts about Timsort that I find genuinely useful to know:

people = [("Ali", 25), ("Sara", 30), ("John", 25)]
sorted_people = sorted(people, key=lambda p: p[1])
print(sorted_people)
# Output: [('Ali', 25), ('John', 25), ('Sara', 30)]
# Ali still appears before John because stability preserves their original relative order

Implementing Bubble Sort Manually (For Understanding)

Even though I never use this in real production code, implementing a basic sorting algorithm by hand was genuinely useful for understanding what “sorting” actually costs computationally. Bubble sort repeatedly steps through the list, comparing adjacent elements and swapping them if they’re in the wrong order:

def bubble_sort(arr):
    numbers = arr.copy()
    n = len(numbers)
    for i in range(n):
        swapped = False
        for j in range(0, n - i - 1):
            if numbers[j] > numbers[j + 1]:
                numbers[j], numbers[j + 1] = numbers[j + 1], numbers[j]
                swapped = True
        if not swapped:
            break   # Already sorted -- stop early
    return numbers

numbers = [9, 3, 7, 1, 5]
print(bubble_sort(numbers))
# Output: [1, 3, 5, 7, 9]

Bubble sort has a worst-case and average-case time complexity of O(n²), because for each of the n elements, it potentially scans through nearly the entire remaining list again. For small lists this is unnoticeable, but it becomes dramatically slower than Timsort as the list size grows — this is exactly why I never use it beyond educational purposes.

Implementing Selection Sort Manually

Another classic algorithm — selection sort repeatedly finds the minimum element from the unsorted portion of the list and moves it to the front:

def selection_sort(arr):
    numbers = arr.copy()
    n = len(numbers)
    for i in range(n):
        min_index = i
        for j in range(i + 1, n):
            if numbers[j] < numbers[min_index]:
                min_index = j
        numbers[i], numbers[min_index] = numbers[min_index], numbers[i]
    return numbers

numbers = [9, 3, 7, 1, 5]
print(selection_sort(numbers))
# Output: [1, 3, 5, 7, 9]

Selection sort is also O(n²) in all cases, but unlike bubble sort, it doesn’t benefit from early termination on already-sorted data — it always performs the same number of comparisons regardless of the input’s initial order.

Comparing Performance: Built-in Sort vs Manual Implementations

import random
import time

data = [random.randint(0, 100000) for _ in range(5000)]

start = time.perf_counter()
sorted(data)
print("Built-in sorted():", time.perf_counter() - start)

start = time.perf_counter()
bubble_sort(data)
print("Bubble sort:", time.perf_counter() - start)

When I’ve run comparisons like this myself, the built-in sorted() function is consistently and dramatically faster — often by two or three orders of magnitude on lists of a few thousand elements — because Timsort is implemented in optimized C code within CPython, while my hand-written Python loops carry the overhead of the Python bytecode interpreter for every single comparison and swap.

Sorting with a Custom Key

Real-world sorting often isn’t as simple as plain ascending numbers — I frequently need to sort by some derived value. The key parameter handles this cleanly:

words = ["banana", "kiwi", "apple", "fig"]
sorted_by_length = sorted(words, key=len)
print(sorted_by_length)
# Output: ['fig', 'kiwi', 'apple', 'banana']

numbers = [-9, 3, -7, 1, 5]
sorted_by_absolute = sorted(numbers, key=abs)
print(sorted_by_absolute)
# Output: [1, 3, 5, -7, -9]

Common Mistakes I’ve Made

Real-World Applications

I use sorted() with a custom key constantly in real projects: sorting a list of file paths by modification date, sorting API results by price or rating, sorting log entries chronologically, or sorting user records alphabetically by last name. Understanding sorting algorithm complexity also matters directly in technical interviews and in situations where I’m evaluating whether a third-party library’s sorting approach is appropriate for very large datasets.

Frequently Asked Questions

What’s the difference between sorted() and .sort()? sorted() returns a new sorted list and leaves the original unchanged; .sort() sorts the list in place and returns None.

What sorting algorithm does Python use internally? Timsort, a hybrid of merge sort and insertion sort, with O(n log n) worst-case and O(n) best-case time complexity.

Should I ever write my own sorting algorithm in real projects? Generally no — Python’s built-in sorted() is faster, more reliable, and more thoroughly tested than a hand-written implementation; manual sorting algorithms are primarily valuable for learning and interviews.

How do I sort numbers entered as strings correctly? Convert each entry to an integer or float with int() or float() before sorting — sorting raw strings compares them lexicographically, not numerically.

Summary

Sorting a list of numbers in Python is, in practice, a one-line task thanks to the built-in sorted() function and Timsort’s excellent real-world performance. But understanding how algorithms like bubble sort and selection sort work by hand — and why they’re O(n²) compared to Timsort’s O(n log n) — gives real insight into why “just use the built-in function” isn’t just convenient advice, it’s actually the objectively better engineering choice in nearly every practical situation.

References

Exit mobile version