代码之美:探索C和Python中的排序艺术

前言

在软件开发领域,了解和掌握多种排序算法是至关重要的。排序不仅是解决许多计算问题的基本步骤,而且在实际应用中,选择适当的排序算法可以显著提高程序的性能。本文将深入探讨使用 C 语言和 Python 实现不同类型数据排序的技术,涉及数组、结构体和字符串的排序方法。通过对排序算法的比较和示例代码的详细解释,读者将能够更好地理解和应用这些关键概念。

文章目录

  • 前言
  • C 语言示例
    • 1. 对 int 类型数组排序
    • 2. 对 char 类型数组排序(同 int 类型)
    • 3. 对 double 类型数组排序(特别要注意)
    • 4. 对结构体一级排序
    • 5. 对结构体二级排序
    • 6. 对字符串进行排序
    • #define
  • Python 示例
    • 1. 对 int 类型数组排序
    • 2. 对 char 类型数组排序(同 int 类型)
    • 3. 对 double 类型数组排序
    • 4. 对结构体一级排序
    • 5. 对结构体二级排序
    • 6. 对字符串进行排序
    • Lambda 函数
  • Lambda 与 #define
  • 总结

C 语言示例

这是关于使用 qsort 函数进行不同类型数组和结构体排序的示例。下面是对每个示例的简要解释:

1. 对 int 类型数组排序

int num[100];

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

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

2. 对 char 类型数组排序(同 int 类型)

char word[100];

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

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

3. 对 double 类型数组排序(特别要注意)

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. 对结构体一级排序

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. 对结构体二级排序

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. 对字符串进行排序

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);

注意:这些示例都假设相应的数组或结构体是已经声明并初始化的。确保引入了 头文件,因为其中包含了 qsortstrcmp 函数的声明。

#define

在C语言中,#define 是一个预处理指令,用于创建宏(macro)。它的主要目的是在编译之前进行文本替换,使得代码更加灵活和易于维护。#define 的语法格式如下:

#define 宏名 替换文本

宏名是一个标识符,通常使用大写字母表示,而替换文本是在代码中出现宏名时将其替换的文本内容。宏可以是简单的值、表达式,甚至是代码块。

以下是一些常见的 #define 的用法:

  1. 定义常量:

    #define PI 3.14159
    

    这样,每次在代码中使用 PI 时,都会被替换为 3.14159

  2. 定义函数宏:

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

    这个宏可以用来计算一个数的平方,例如 SQUARE(5) 会被替换为 (5 * 5)

  3. 条件编译:

    #define DEBUG
    

    在代码中使用 #ifdef DEBUG 可以根据是否定义了 DEBUG 来包含或排除调试代码。

  4. 字符串拼接:

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

    这个宏可以将两个标识符连接在一起,例如 CONCAT(var, 1) 可以被替换为 var1

请注意,宏的替换是简单的文本替换,可能会导致一些问题,因此在使用宏时需要小心。例如,在定义函数宏时,要确保使用括号将参数括起来,以避免意外的运算顺序问题。

Python 示例

在Python中,你可以使用内置的 sorted 函数和自定义的比较函数来实现这些功能。下面是相应的示例:

1. 对 int 类型数组排序

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

sorted_num = sorted(num)

2. 对 char 类型数组排序(同 int 类型)

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

sorted_word = sorted(word)

3. 对 double 类型数组排序

in_data = [2.5, 1.0, 3.7, 2.0]

sorted_in_data = sorted(in_data)

4. 对结构体一级排序

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. 对结构体二级排序

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. 对字符串进行排序

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)

这里,key 参数用于指定排序时的关键字,而 lambda 函数用于定义比较规则。请注意,这里的排序是升序的,如果需要降序,可以在 sorted 函数中使用 reverse=True 参数。

Lambda 函数

lambda 函数是一种在 Python 中创建匿名函数的方式。它的语法形式是简洁的,适用于一次性、简单的操作。lambda 函数的基本结构如下:

lambda arguments: expression

下面是一个简单的例子,演示了 lambda 函数的用法:

# 使用普通函数
def add(x, y):
    return x + y

# 使用lambda函数
add_lambda = lambda x, y: x + y

# 调用
result1 = add(2, 3)
result2 = add_lambda(2, 3)

print(result1)  # 输出 5
print(result2)  # 输出 5

在上述例子中,lambda x, y: x + y 等效于普通函数 def add(x, y): return x + ylambda 函数通常用于需要一个简单函数的地方,特别是在函数参数中传递函数的时候,或者在一些短暂的代码块内。

下面是一个更复杂的例子,结合了内置函数 sortedkey 参数和 lambda 函数:

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

# 使用lambda函数作为排序的key
sorted_data = sorted(data, key=lambda x: x[1])

print(sorted_data)

在这个例子中,lambda x: x[1] 表示按照元组中的第二个元素进行排序。lambda 函数的使用可以使代码更为简洁,特别是在涉及短小的操作时。

Lambda 与 #define

继续讨论之前的C代码例子,我们可以将其中的宏和函数用Python的Lambda表达式和函数定义来替代。

首先,我们来处理一些宏定义:

#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&(-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
#define PI 3.14159265358979323

使用Lambda表达式和常量:

# Lambda 表达式替代宏
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 & -a
my_sqr = lambda a: a * a
my_swap = lambda a, b: (b, a)
my_mem = lambda a, b: [b] * len(a)

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

接下来,我们将处理主函数中的一些部分:

int main() {
    int x = 0;
    int &b = x;
    int p = &x;

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

这里有一些问题,因为在Python中,引用的概念不同于C。在Python中,没有直接的引用,而是通过对象的引用来实现。修改后的代码如下:

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])

在这里,我们使用列表 x 来模拟C中的引用,因为列表是可变对象,可以在函数内修改。这样就保留了原有的逻辑。在Python中,通常更推荐使用函数参数和返回值来传递和获取结果,而不是使用引用。
在这个例子中,我使用列表 x 作为可变对象,以模拟C中的引用。这种方式在Python中更为常见,因为Python中的变量是对象的引用。接下来,我们将处理Lambda函数和#define的替代。

# Lambda 表达式替代 #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 & -a
my_sqr = lambda a: a * a
my_swap = lambda a, b: (b, a)
my_mem = lambda a, b: [b] * len(a)

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

上述代码中,我使用Lambda表达式替代了一些常见的宏定义,例如minmaxabs等。Lambda表达式在这里更具可读性,同时也更符合Python的风格。

最后,我们将主函数的部分修改为适应Python的语法:

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()

在Python中,函数参数的传递方式是按对象引用传递,所以不需要使用&符号,直接传递对象即可。同时,我将主函数的部分放入了main函数,并添加了if __name__ == "__main__":来确保在直接运行脚本时执行。

总结

本文一个针对C语言中使用 qsort 函数进行不同类型数组和结构体排序的示例,以及相应的Python代码和关于lambda的讨论。

在C语言示例中,使用了#define来定义一些常用的宏,如最小值、最大值、绝对值等,以及一些常量。在Python中,这些宏可以使用Lambda表达式来替代,同时还展示了对数组和结构体的排序以及一些注意事项。

在Python示例中,使用了内置的 sorted 函数和Lambda表达式,展示了如何对不同类型的数据进行排序,包括整数数组、字符数组、浮点数数组、结构体数组等。此外,还对结构体进行了一级和二级排序,以及对字符串进行排序。

在最后的讨论中,解释了lambda函数的基本结构和用法,并展示了如何使用Lambda表达式替代C语言中的宏。

注意:在Python示例中,由于Python中没有指针和引用的概念,对于模拟引用的部分使用了可变对象(列表)。这是因为在Python中,函数参数是通过传递对象的引用来实现的,但对于不可变对象(如整数),函数内的修改不会影响到外部变量。

你可能感兴趣的:(python,C++,开发语言,c++,python)