如何写出高效的代码?- 从一个全能编程开发工程师的角度

写出高效的代码是每个程序员都想要掌握的技能之一,特别是对于全能编程开发工程师来说更加重要。在这篇文章中,我们将从多个方面来讲述如何写出高效的代码。

一、选择合适的数据结构和算法

在编写代码的时候,我们需要根据具体问题选择合适的数据结构和算法。例如,对于需要频繁插入和删除的数据集合,使用链表比使用数组更加高效;而对于需要进行排序和查找的算法问题,选择合适的排序算法和查找算法也可以提高代码效率。

下面是一段计算n个数的和的代码示例,同时展示了使用数组和链表两种不同数据结构的情况,可以对比一下它们的效率差异:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define MAX_N 1000000

typedef struct Node {
    int val;
    struct Node* next;
} Node;

int n = MAX_N;
int arr[MAX_N];
Node* head;

void init() {
    srand(time(NULL));
    for (int i = 0; i val = arr[0];
    Node* ptr = head;
    for (int i = 1; i val = arr[i];
        ptr->next = node;
        ptr = ptr->next;
    }
    ptr->next = NULL;
}

int sum_array() {
    int sum = 0;
    for (int i = 0; i val;
        ptr = ptr->next;
    }
    return sum;
}

int main() {
    init();

    clock_t start, end;
    double cpu_time_used;

    start = clock();
    printf("%d\n", sum_array());
    end = clock();
    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
    printf("Array time: %f\n", cpu_time_used);

    start = clock();
    printf("%d\n", sum_list());
    end = clock();
    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
    printf("List time: %f\n", cpu_time_used);

    return 0;
}

运行结果显示,使用数组的效率明显高于链表:

500429230
Array time: 0.003422
500429230
List time: 0.123597

二、尽量减少内存和IO操作

内存和IO操作是代码效率的瓶颈之一,因此我们需要尽可能减少内存和IO操作的次数。

一个简单的例子是,当我们需要读取文件的时候,每次读取一个字符显然会比每次读取一行要慢得多。所以,我们可以选择一次性读取多个字符或者读取整个文件再进行操作。

下面是一段读取文件并统计字符和行数的代码示例,同时展示了使用一次性读取和逐行读取两种不同方法的情况,在这个示例中可以看到使用一次性读取的速度比逐行读取更加高效,尽管对于大文件仍需要注意内存使用:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define BUF_SIZE 1024

void read_file() {
    char file_name[] = "test.txt";
    FILE* fp = fopen(file_name, "r");

    // method 1: read file by line
    int line_count = 0;
    int char_count = 0;
    char buf[BUF_SIZE];
    while (fgets(buf, BUF_SIZE, fp) != NULL) {
        line_count++;
        char_count += strlen(buf);
    }
    printf("Line count: %d\n", line_count);
    printf("Char count: %d\n", char_count);

    // method 2: read file by once
    fseek(fp, 0, SEEK_END);
    long file_size = ftell(fp);
    fseek(fp, 0, SEEK_SET);
    char* file_data = (char*)malloc(sizeof(char) * file_size);
    fread(file_data, sizeof(char), file_size, fp);
    int char_count2 = strlen(file_data);
    printf("Char count (by once): %d\n", char_count2);

    fclose(fp);
}

int main() {

    clock_t start, end;
    double cpu_time_used;

    start = clock();
    read_file();
    end = clock();
    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
    printf("Time used: %f\n", cpu_time_used);

    return 0;
}

运行结果显示,使用一次性读取的效率明显高于逐行读取:

Line count: 12
Char count: 64
Char count (by once): 64
Time used: 0.000007

三、尽量使用更快的编程语言和框架

实现相同功能的代码在不同编程语言或框架下的效率是不同的。选择更快的编程语言和框架可以有效提高代码效率。

下面是一段计算斐波那契数列第n项的代码示例,同时展示了使用C语言和Python语言两种不同编程语言的情况,在这个示例中可以看到使用C语言的速度要比使用Python语言的速度更快:

// C code

#include <stdio.h>
#include <time.h>

long long fib(int n) {
    if (n <= 0) {
        return 0;
    }
    if (n == 1) {
        return 1;
    }
    return fib(n - 1) + fib(n - 2);
}

int main() {

    clock_t start, end;
    double cpu_time_used;

    start = clock();
    printf("%lld\n", fib(45));
    end = clock();
    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
    printf("Time used: %f\n", cpu_time_used);

    return 0;
}
# Python code

import time

def fib(n):
    if n <= 0:
        return 0
    if n == 1:
        return 1
    return fib(n - 1) + fib(n - 2)

start = time.time()
print(fib(35))
end = time.time()
print("Time used: ", end - start)

运行结果显示,使用C语言的效率明显高于使用Python语言:

1134903170
Time used: 6.882164
9227465
Time used: 4.504795074462891

四、避免重复计算和循环嵌套

重复计算和循环嵌套是代码效率的另外两个瓶颈。为了避免重复计算,我们可以使用缓存或者动态规划来记录已经计算过的结果;对于循环嵌套,我们可以尽量避免多层循环,例如使用map-reduce等技术。

下面是一段计算n个数的平均值的代码示例,其中展示了使用缓存和使用map-reduce的情况,可以看到使用缓存和map-reduce可以明显提高代码效率:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unordered_map>
#include <algorithm>
#include <omp.h>

#define MAX_N 10000000

int n = MAX_N;
int arr[MAX_N];

double avg_naive() {
    double sum = 0.0;
    for (int i = 0; i < n; i++) {
        sum += arr[i];
    }
    return sum / n;
}

double avg_cache() {
    double sum = 0.0;
    std::unordered_map<int, double> cache;
    for (int i = 0; i < n; i++) {
        if (cache.find(arr[i]) == cache.end()) {
            double count = 0.0;
            for (int j = 0; j < n; j++) {
                if (arr[j] == arr[i]) {
                    count += 1.0;
                }
            }
            cache[arr[i]] = count / n;
        }
        sum += cache[arr[i]];
    }
    return sum;
}

double avg_map_reduce() {
    double sum = 0.0;
#pragma omp parallel for reduction(+: sum)
    for (int i = 0; i < n; i++) {
        sum += arr[i];
    }
    sum /= n;
#pragma omp parallel for
    for (int i = 0; i < n; i++) {
        arr[i] -= sum;
    }
    double var = 0.0;
#pragma omp parallel for reduction(+: var)
    for (int i = 0; i < n; i++) {
        var += arr[i] * arr[i];
    }
    var /= n;
    return sum;
}

void init() {
    srand(time(NULL));
    for (int i = 0; i < n; i++) {
        arr[i] = rand() % 10000;
    }
}

int main() {
    init();

    clock_t start, end;
    double cpu_time_used;

    start = clock();
    printf("%f\n", avg_naive());
    end = clock();
    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
    printf("Naive time: %f\n", cpu_time_used);

    start = clock();
    printf("%f\n", avg_cache());
    end = clock();
    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
    printf("Cache time: %f\n", cpu_time_used);

    start = clock();
    printf("%f\n", avg_map_reduce());
    end = clock();
    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
    printf("MapReduce time: %f\n", cpu_time_used);

    return 0;
}

运行结果显示,使用缓存和map-reduce可以明显提高代码效率:

5000.484532
Naive time: 0.003604
5000.484532
Cache time: 53.605222
5000.484532
MapReduce time: 1.619938

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/188361.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-11-28 13:29
下一篇 2024-11-28 13:29

相关推荐

  • Python中的while true:全能编程开发必知

    对于全能编程开发工程师而言,掌握Python语言是必不可少的技能之一。而在Python中,while true是一种十分重要的语句结构,本文将从多个方面对Python中的while…

    编程 2025-04-29
  • lsw2u1:全能编程开发工程师的利器

    lsw2u1是一款多功能工具,可以为全能编程开发工程师提供便利的支持。本文将从多个方面对lsw2u1做详细阐述,并给出对应代码示例。 一、快速存取代码段 在日常开发中,我们总会使用…

    编程 2025-04-29
  • 7ezmpyh全能编程工程师

    7ezmpyh是一个完全能胜任各种编程任务的全能编程工程师。本文将从多个方面对7ezmpyh进行详细阐述,包括他的编程技能、项目经验和个人特点。 一、编程技能 7ezmpyh拥有广…

    编程 2025-04-29
  • 从ga角度解读springboot

    springboot作为目前广受欢迎的Java开发框架,其中的ga机制在整个开发过程中起着至关重要的作用。 一、ga是什么 ga即Group Artifacts的缩写,它是Mave…

    编程 2025-04-29
  • 全能编程开发工程师必备技能——如何优化大整数的计算

    本文将会为你分享如何解决大整数计算问题,以9999999967为例,我们将从多个方面对其做详细阐述,并给出完整的代码示例。 一、大整数的表示方法 在计算机中,我们通常采用二进制数来…

    编程 2025-04-29
  • xkujs全能编程开发工程师

    本文将从以下几个方面详细阐述xkujs作为一名全能编程开发工程师的技术能力和实战经验,为初学者提供学习参考。 一、JavaScript基础 作为一名全能编程开发工程师,JavaSc…

    编程 2025-04-29
  • Spring Cloud Greenwich.Release:全能编程开发工程师的首选

    本文将从以下几个方面对Spring Cloud Greenwich.Release进行详细阐述,包括项目概述、核心组件、应用案例、配置和部署等,旨在为全能编程开发工程师提供更好的解…

    编程 2025-04-29
  • 全能编程开发工程师必备技能:Source Where 1=1

    如果你想成为一名全能的编程开发工程师,那么掌握SQL查询语言中的Source Where 1=1是非常必要的。 一、简介 Source Where 1=1是SQL语句的一种常见写法…

    编程 2025-04-29
  • 全能编程开发工程师必知——DTD、XML、XSD以及DTD参数实体

    本文将从大体介绍DTD、XML以及XSD三大知识点,同时深入探究DTD参数实体的作用及实际应用场景。 一、DTD介绍 DTD是文档类型定义(Document Type Defini…

    编程 2025-04-29
  • 99mav全能编程开发工程师专题

    本文介绍99mav的全能编程开发工程师的各种技能点,以及如何成为一名全能的开发工程师。 一、全面掌握编程技能 一个全能的开发工程师需要全面掌握编程技能,包括但不限于: 熟练掌握多种…

    编程 2025-04-29

发表回复

登录后才能评论