The Beauty of Code: Exploring the Art of Sorting in C and Python

Foreword

In the field of software development, it is crucial to understand and master multiple sorting algorithms. Sorting is not only a fundamental step in solving many computational problems, but in practical applications, choosing an appropriate sorting algorithm can significantly improve the performance of a program. This article will delve into techniques for sorting different types of data using C language and Python, involving sorting methods for arrays, structures, and strings. Through a comparison of sorting algorithms and detailed explanations of example code, readers will be able to better understand and apply these key concepts.

Article directory

  • Preface
  • C language example
    • 1. Sort int type array
    • 2. Sort char type array (same as int type)
    • 3. Sort double type arrays (pay special attention)
    • 4. Sort the structure at the first level
    • 5. Secondary sorting of structures
    • 6. Sort strings
    • #define
  • Python example
    • 1. Sort int type array
    • 2. Sort char type array (same as int type)
    • 3. Sort double type array
    • 4. Sort the structure at the first level
    • 5. Secondary sorting of structures
    • 6. Sort strings
    • Lambda function
  • Lambda and #define
  • Summarize

C language example

This is an example of using the qsort function to sort arrays and structures of different types. Here’s a brief explanation of each example:

1. Sort int type array

int num[100];

int cmp(const void *a, const void *b) {<!-- -->
    return (*(int *)a - *(int *)b);
}

qsort(num, 100, sizeof(num[0]), cmp);

2. Sort char type array (same as int type)

char word[100];

int cmp(const void *a, const void *b) {<!-- -->
    return (*(char *)a - *(int *)b);
}

qsort(word, 100, sizeof(word[0]), cmp);

3. Sort double type arrays (pay special attention)

double in[100];

int cmp(const void *a, const void *b) {<!-- -->
    return (*(double *)a > *(double *)b ? 1 : -1);
}

qsort(in, 100, sizeof(in[0]), cmp);

4. First-level sorting of structures

struct In {<!-- -->
    double data;
    int other;
} s[100];

int cmp(const void *a, const void *b) {<!-- -->
    return (((In *)a)->data > ((In *)b)->data ? 1 : -1);
}

qsort(s, 100, sizeof(s[0]), cmp);

5. Secondary sorting of structures

struct In {<!-- -->
    int x;
    int y;
} s[100];

int cmp(const void *a, const void *b) {<!-- -->
    struct In *c = (In *)a;
    struct In *d = (In *)b;
    if (c->x != d->x) return c->x - d->x;
    else return d->y - c->y;
}

qsort(s, 100, sizeof(s[0]), cmp);

6. Sort strings

struct In {<!-- -->
    int data;
    char str[100];
} s[100];

int cmp(const void *a, const void *b) {<!-- -->
    return strcmp(((In *)a)->str, ((In *)b)->str);
}

qsort(s, 100, sizeof(s[0]), cmp);

Note: These examples assume that the corresponding array or structure has been declared and initialized. Make sure to include the and header files, as they include qsort and strcmp declaration of function.

#define

In C language, #define is a preprocessing directive used to create macros. Its main purpose is to perform text replacement before compilation, making the code more flexible and easier to maintain. The syntax format of #define is as follows:

#define macro name replacement text

The macro name is an identifier, usually represented by uppercase letters, and the replacement text is the text that replaces the macro name when it appears in the code. Macros can be simple values, expressions, or even blocks of code.

Here are some common uses of #define:

  1. Define constants:

    #define PI 3.14159
    

    This way, every time PI is used in your code, it will be replaced by 3.14159.

  2. Define function macro:

    #define SQUARE(x) ((x) * (x))
    

    This macro can be used to calculate the square of a number, for example SQUARE(5) will be replaced by (5 * 5).

  3. Conditional compilation:

    #define DEBUG
    

    Use #ifdef DEBUG in your code to include or exclude debug code based on whether DEBUG is defined.

  4. String concatenation:

    #define CONCAT(x, y) x ## y
    

    This macro can concatenate two identifiers together, for example CONCAT(var, 1) can be replaced by var1.

Please note that the macro’s replacement is a simple text replacement and may cause some problems, so you need to be careful when using macros. For example, when defining a function macro, be sure to use parentheses to surround the parameters to avoid unexpected order of operations problems.

Python examples

In Python, you can use the built-in sorted function and custom comparison functions to achieve these functions. Here are the corresponding examples:

1. Sort int type array

num = [2, 4, 1, 7, 5]

sorted_num = sorted(num)

2. Sort char type array (same as int type)

word = ['b', 'a', 'd', 'c']

sorted_word = sorted(word)

3. Sort double type array

in_data = [2.5, 1.0, 3.7, 2.0]

sorted_in_data = sorted(in_data)

4. First-level sorting of structures

class In:
    def __init__(self, data, other):
        self.data = data
        self.other = other

s = [In(2.5, 1), In(1.0, 3), In(3.7, 2)]

sorted_s = sorted(s, key=lambda x: x.data)

5. Secondary sorting of structures

class In:
    def __init__(self, x, y):
        self.x = x
        self.y = y

s = [In(2, 5), In(1, 8), In(2, 3)]

sorted_s = sorted(s, key=lambda x: (x.x, -x.y))

6. Sort strings

class In:
    def __init__(self, data, str):
        self.data = data
        self.str = str

s = [In(2, 'apple'), In(1, 'banana'), In(3, 'orange')]

sorted_s = sorted(s, key=lambda x: x.str)

Here, the key parameter is used to specify the key when sorting, and the lambda function is used to define the comparison rule. Please note that the sorting here is in ascending order. If you need descending order, you can use the reverse=True parameter in the sorted function.

Lambda function

lambda functions are a way to create anonymous functions in Python. Its grammatical form is concise and suitable for one-time, simple operations. The basic structure of the lambda function is as follows:

lambda arguments: expression

Here is a simple example demonstrating the use of the lambda function:

# Use normal functions
def add(x, y):
    return x + y

# Use lambda function
add_lambda = lambda x, y: x + y

# transfer
result1 = add(2, 3)
result2 = add_lambda(2, 3)

print(result1) # Output 5
print(result2) # Output 5

In the above example, lambda x, y: x + y is equivalent to the ordinary function def add(x, y): return x + y. The lambda function is usually used where a simple function is needed, especially when passing a function in a function parameter, or within some short-lived block of code.

Here is a more complex example that combines the key argument of the built-in function sorted with the lambda function:

data = [(1, 5), (3, 2), (2, 8)]

# Use lambda function as sorting key
sorted_data = sorted(data, key=lambda x: x[1])

print(sorted_data)

In this example, lambda x: x[1] means to sort by the second element in the tuple. The use of lambda functions can make code more concise, especially when short operations are involved.

Lambda and #define

Continuing with the previous C code example, we can replace the macros and functions with Python Lambda expressions and function definitions.

First, let’s deal with some macro definitions:

#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abs(a) ((a)>0?(a):(-(a)))
#define lowbit(a) (a & amp;(-a))
#define sqr(a) ((a)*(a))
#define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
#define mem(a,b) memset(a,b,sizeof(a))
#define eps (1e-10)
#define J 10000
#define mod 1000000007
#define MAX 0x7f7f7f7f
#definePI 3.14159265358979323

Use lambda expressions and constants:

# Lambda expression replacement macro
my_min = lambda a, b: a if a < b else b
my_max = lambda a, b: a if a > b else b
my_abs = lambda a: a if a > 0 else -a
lowbit = lambda a: a & amp; -a
my_sqr = lambda a: a * a
my_swap = lambda a, b: (b, a)
my_mem = lambda a, b: [b] * len(a)

# constant
eps=1e-10
J=10000
mod=1000000007
MAX = 0x7f7f7f7f
PI = 3.14159265358979323

Next, we’ll tackle some parts of the main function:

int main() {<!-- -->
    int x = 0;
    int &b = x;
    int p = &x;

    printf("%d\t", x);
    printf("%d\t", *p);
    printf("%d\
", b);
    printf("%p\t", & amp;x);
    printf("%p\t", & amp;b);
    printf("%p\
", p);
    fun_1(x);
    printf("%d\t", x);
    fun_2(x);
    printf("%d\t", x);
    fun_3(p);
    printf("%d\t", x);
    return 0;
}

There are some problems here because in Python the concept of references is different from C. In Python, there are no direct references, but references to objects. The modified code is as follows:

def fun_1(a):
    a=5

def fun_2(a):
    a=5

def fun_3(a):
    a[0] = 5

def swap(a, b):
    a, b = b, a
    return a, b

x = [0]
b = x
p = x

print(x[0])
print(p[0])
print(b[0])
print(id(x[0]))
print(id(b[0]))
print(id(p[0]))

fun_1(x)
print(x[0])

fun_2(x)
print(x[0])

fun_3(x)
print(x[0])

Here, we use a list x to simulate a reference in C, since lists are mutable objects and can be modified within functions. This way the original logic is retained. In Python, it is generally recommended to use function parameters and return values to pass and get results rather than using references.
In this example, I’m using the list x as a mutable object to simulate a reference in C. This approach is more common in Python because variables in Python are references to objects. Next, we’ll deal with Lambda functions and #define substitutions.

# Lambda expression replacement #define
my_min = lambda a, b: a if a < b else b
my_max = lambda a, b: a if a > b else b
my_abs = lambda a: a if a > 0 else -a
lowbit = lambda a: a & amp; -a
my_sqr = lambda a: a * a
my_swap = lambda a, b: (b, a)
my_mem = lambda a, b: [b] * len(a)

# constant
eps=1e-10
J=10000
mod=1000000007
MAX = 0x7f7f7f7f
PI = 3.14159265358979323

In the above code, I used Lambda expressions to replace some common macro definitions, such as min, max, abs, etc. Lambda expressions are more readable here and more Pythonic.

Finally, we modified the main function part to adapt to Python syntax:

def main():
    x = [0]
    b = x
    p = x

    print(x[0])
    print(p[0])
    print(b[0])
    print(id(x[0]))
    print(id(b[0]))
    print(id(p[0]))

    fun_1(x)
    print(x[0])

    fun_2(x)
    print(x[0])

    fun_3(x)
    print(x[0])

if __name__ == "__main__":
    main()

In Python, function parameters are passed by object reference, so there is no need to use the & symbols, just pass the object directly. At the same time, I put the main function part into the main function and added if __name__ == "__main__": to ensure execution when running the script directly.

Summary

This article is an example of using the qsort function to sort different types of arrays and structures in C language, as well as the corresponding Python code and discussion about lambda.

In the C language example, #define is used to define some commonly used macros, such as minimum value, maximum value, absolute value, etc., as well as some constants. In Python, these macros can be replaced by Lambda expressions, and sorting of arrays and structures is also shown along with some considerations.

In the Python example, the built-in sorted function and Lambda expression are used to show how to sort different types of data, including integer arrays, character arrays, floating point arrays, structure arrays, etc. In addition, primary and secondary sorting of structures is performed, as well as sorting of strings.

In the final discussion, the basic structure and usage of lambda functions are explained, and how to use lambda expressions to replace macros in C language.

Note: In the Python example, since there is no concept of pointers and references in Python, mutable objects (lists) are used for the part that simulates references. This is because in Python, function parameters are implemented by passing references to objects, but for immutable objects (such as integers), modifications within the function will not affect external variables.