【数组与链表】数组的基本演绎法与排序“大乱斗”

1 概述

1.1 案例介绍

在现代软件开发中,数据结构的选择对程序的性能和可维护性有着至关重大的影响。数组和链表作为两种最基本的数据结构,分别适用于不同的场景。理解它们的特性和优劣,能够协助开发者在实际项目中做出更合理的技术选型,从而优化系统性能。

在C语言中,数组是高效处理批量数据的基石。其连续内存结构直接映射硬件特性,通过下标实现O(1)时间复杂度的随机访问,为算法(如排序、搜索)和底层系统开发(操作系统内核表、嵌入式寄存器映射)提供了不可替代的性能优势。

本案例相关实验将在华为云开发者空间云主机进行,开发者空间云主机为开发者提供了高效稳定的云资源,确保用户的数据安全。云主机当前已适配完整的C/C++开发环境,支持Visual Studio Code等多种IDE工具安装调测。

1.2 适用对象

  • 个人开发者
  • 高校学生

1.3 案例时间

本案例总时长预计40分钟。

1.4 案例流程

【数组与链表】数组的基本演绎法与排序“大乱斗”

说明:

  1. 开通开发者空间,搭建C/C++开发环境。
  2. 打开VS Code,编写代码运行程序。

最新案例动态,请查阅《【数组与链表】数组的基本演绎法与排序“大乱斗”》「链接」。小伙伴快来领取华为开发者空间进行实操吧!

1.5 资源总览

本案例预计花费总计0元。

资源名称

规格

单价(元)

时长(分钟)

开发者空间-云主机

4vCPUs | 8GB | ARM | Ubuntu | Ubuntu 24.04 Server定制版

免费

40

VS Code

1.97.2

免费

40

2 配置实验环境

2.1 开发者空间配置

面向广大开发者群体,华为开发者空间提供一个随时访问的“开发桌面云主机”、丰富的“预配置工具集合”和灵活使用的“场景化资源池”,开发者开箱即用,快速体验华为根技术和资源。

如果还没有领取开发者空间云主机,可以参考免费领取云主机文档领取。

领取云主机后可以直接进入华为开发者空间工作台界面,点击打开云主机 > 进入桌面连接云主机。

【数组与链表】数组的基本演绎法与排序“大乱斗”

【数组与链表】数组的基本演绎法与排序“大乱斗”

2.2 配置实验环境

参考案例中心《基于开发者空间,定制C&C++开发环境云主机镜像》“2. 实验环境搭建”、“3. VS Code安装部署”章节完成开发环境、VS code及插件安装。

【数组与链表】数组的基本演绎法与排序“大乱斗”

3 数组的基本操作

3.1 数组基础概念

数组是一组连续内存空间中存储的一样类型数据元素的集合。

数组的声明与访问,具体代码操作如下:

Step1:复制以下代码,替换main.cpp文件中的代码。

#include <iostream>
using namespace std;
int main() {
    // 数组声明与初始化
    // 声明一个包含5个整数的数组
    int numbers[5]; 
    // 声明并初始化
    int primes[] = {2, 3, 5, 7, 11};
    // 访问数组元素
    numbers[0] = 10; // 第一个元素的索引是0
    numbers[4] = 50; // 最后一个元素的索引是4

    printf("数组大小:%ld字节
", sizeof(numbers));
    printf("元素个数:%ld
", sizeof(numbers)/sizeof(numbers[0]));
    printf("数组地址:%p
", (void*)numbers);
    printf("第一个元素地址:%p
", (void*)&numbers[0]);
    printf("数组第一个元素: %d
", primes[0]);  
    printf("数组最后一个元素: %d
", primes[4]);  
return 0;
}

Step2:点击编辑器左上角运行按钮直接运行,Terminal窗口可以看到打印内容。

【数组与链表】数组的基本演绎法与排序“大乱斗”

3.2 一维数组操作

在C语言中,一维数组是一种基础数据结构,用于在连续内存空间中存储一样类型的多个元素。对一维数组的操作包括数组的最大值、数组最小值、数组平均值、数组反转和数组排序等。

具体代码操作如下:

Step1:复制以下代码,替换main.cpp文件中的代码。

#include <iostream>
using namespace std;

// 函数声明
void printArray(int arr[], int size);
void reverseArray(int arr[], int size);
int findMax(int arr[], int size);
int findMin(int arr[], int size);
float calculateAverage(int arr[], int size);
void bubbleSort(int arr[], int size);

int main() {
    int arr[] = {8, 3, 6, 2, 9, 1, 4, 7, 5};
    int size = sizeof(arr)/sizeof(arr[0]);
    
    printf("原始数组:");
    printArray(arr, size);
    
    printf("数组反转:");
    reverseArray(arr, size);
    printArray(arr, size);
    
    printf("最大值:%d
", findMax(arr, size));
    printf("最小值:%d
", findMin(arr, size));
    printf("平均值:%.2f
", calculateAverage(arr, size));
    
    printf("排序后:");
    bubbleSort(arr, size);
    printArray(arr, size);
return 0;
}

// 打印数组
void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("
");
}

// 反转数组
void reverseArray(int arr[], int size) {
    for (int i = 0; i < size/2; i++) {
        int temp = arr[i];
        arr[i] = arr[size-1-i];
        arr[size-1-i] = temp;
    }
}

// 查找最大值
int findMax(int arr[], int size) {
    int max = arr[0];
    for (int i = 1; i < size; i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
    }
    return max;
}

// 查找最小值
int findMin(int arr[], int size) {
    int min = arr[0];
    for (int i = 1; i < size; i++) {
        if (arr[i] < min) {
            min = arr[i];
        }
    }
    return min;
}

// 计算平均值
float calculateAverage(int arr[], int size) {
    int sum = 0;
    for (int i = 0; i < size; i++) {
        sum += arr[i];
    }
    return (float)sum / size;
}

// 冒泡排序
void bubbleSort(int arr[], int size) {
    for (int i = 0; i < size-1; i++) {
        for (int j = 0; j < size-i-1; j++) {
            if (arr[j] > arr[j+1]) {
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
}

Step2:点击编辑器左上角运行按钮直接运行,Terminal窗口可以看到打印内容。

【数组与链表】数组的基本演绎法与排序“大乱斗”

3.3 二维数组操作

在C语言中,二维数组本质上是“数组的数组”,可视为由行和列组成的表格结构。对二维数组的操作包括打印二维数组、二维数组元素访问、遍历二维数组。

具体代码操作如下:

Step1:复制以下代码,替换main.cpp文件中的代码。

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

void printArray2(int *arr, int rows, int cols);

int main() {
    int matrixA[2][3] = {
        {1, 2, 3},
        {4, 5, 6}
    };

    printf("矩阵A:
");
    printArray2(&matrixA[0][0], 2, 3);

    // 二维数组元素访问
    // 修改第2行第3列元素(索引从0开始)    
    matrixA[1][2] = 10; 
    // 读取第1行第2列元素(val=2)     
    int val = matrixA[0][1]; 
    printf("读取第1行第2列元素: %d
", val); 
    printArray2(&matrixA[0][0], 2, 3);

    //遍历二维数组
    printf("遍历二维数组:
"); 
    for(int i=0; i<2; i++) {        
        for(int j=0; j<3; j++) {    
            printf("%d ", matrixA[i][j]);
        }
        printf("
");
    }

    return 0;
}

void printArray2(int *arr, int rows, int cols) {
    for(int i = 0; i < rows; i++) {
        for(int j = 0; j < cols; j++) {
            // 计算元素位置:当前行首地址 + 列偏移
            printf("%2d ", *(arr + i * cols + j));
        }
        printf("
");
    }
}

Step2:点击编辑器左上角运行按钮直接运行,Terminal窗口可以看到打印内容。

【数组与链表】数组的基本演绎法与排序“大乱斗”

3.4 字符数组与字符串

字符数组:

在C语言中,字符数组是存储字符序列(包括字符串)的基本结构。它既是普通数组的特例(元素类型为char),也是表明字符串的基础。字符数组的操作包括访问元素、修改元素、遍历元素。

具体代码操作如下:

Step1:复制以下代码,替换main.cpp文件中的代码。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
    char letters[5] = {'a','b','c','d','e'};
    // 访问元素
    char first = letters[0]; 
    printf("字符数组第一个元素:%c ",first);
    printf("
");
    // 修改元素
    // 数组变为 {'a','z','c','d','e'}
    letters[1] = 'z'; 
    size_t len = sizeof(letters);
    printf("修改后的字符数组元素为:");
    for (int i = 0; i < len; i++) {
        printf("%c ", letters[i]); 
    }
    printf("
");
    // 遍历
    printf("遍历字符数组元素:");
    for (int i = 0; i < sizeof(letters); i++) {
        printf("%c ", letters[i]);
    }
    printf("
");
    // 添加终止符,成为字符串
    letters[5] = '';
    // 目前可以安全使用字符串函数
    printf("字符数组转换成字符串:%s", letters); 
    printf("
");
    return 0;
}

void printArray2(int *arr, int rows, int cols) {
    for(int i = 0; i < rows; i++) {
        for(int j = 0; j < cols; j++) {
            // 计算元素位置:当前行首地址 + 列偏移
            printf("%2d ", *(arr + i * cols + j));
        }
        printf("
");
    }
}

Step2:点击编辑器左上角运行按钮直接运行,Terminal窗口可以看到打印内容。

【数组与链表】数组的基本演绎法与排序“大乱斗”

字符串:

字符串的复制、连接、比较等。

Step1:复制以下代码,替换main.cpp文件中的代码。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {

    // 定义字符串
    // 自动计算长度(12字节:11字符+1'')
    char s1[] = "Hello World"; 
    printf("字符串s1: %s
", s1);

    // 字符串长度
    int len = strlen("Hello"); 
    printf("字符串s1的长度: %d
", len);   

    // 字符串的复制
    char source[] = "Hello C"; 
    char dest[20];
    // 安全复制
    strncpy(dest, source, sizeof(dest) - 1); 
    // 确保终止
    dest[sizeof(dest) - 1] = ''; 
    printf("复制字符串dest: %s
", dest);

    // 字符串连接
    char str[50] = "你好,";
    // 安全连接
    strncat(str, "C语言!", sizeof(str) - strlen(str) - 1); 
    printf("复制字符串str: %s
", str);

    // 字符串比较
    int result = strcmp("apple", "banana"); 
    printf("字符串比较result: %d
", result);   
    result = strcmp("apple", "apple"); 
    printf("字符串比较result: %d
", result);   
    result = strcmp("banana", "apple"); 
    printf("字符串比较result: %d
", result);   
    return 0;
}

Step2:点击编辑器左上角运行按钮直接运行,Terminal窗口可以看到打印内容。

【数组与链表】数组的基本演绎法与排序“大乱斗”

4 综合案例:学生成绩管理系统

4.1 功能需求分析

学生成绩管理系统设计功能如下:

  1. 打印出所有学生的考试成绩;
  2. 计算出全班学生的平均分和最高分;
  3. 所有学生的平均分按照降序排列;
  4. 统计学生成绩分布情况(优秀、良好、中等、及格、不及格)。

4.2 代码实现及验证

Step1:复制以下代码,替换main.cpp文件中的代码。

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

// 函数声明
void studentManagementSystem();

int main() {
    printf("
=== 综合案例:学生成绩管理系统 ===
");
    studentManagementSystem();
    return 0;
}

// 综合案例:学生成绩管理系统
void studentManagementSystem() {
    #define MAX_STUDENTS 100
    #define MAX_NAME_LENGTH 50
    
    typedef struct {
        int id;
        char name[MAX_NAME_LENGTH];
        float scores[3]; // 三门课程的成绩
        float average;
    } Student;
    
    Student students[MAX_STUDENTS];
    int count = 0;
    
    printf("
--- 学生成绩管理系统 ---
");
    
    // 添加学生数据
    students[count++] = (Student){1, "张三", {85, 90, 78}};
    students[count++] = (Student){2, "李四", {92, 88, 95}};
    students[count++] = (Student){3, "王五", {76, 85, 80}};
    
    // 计算平均分
    for (int i = 0; i < count; i++) {
        float sum = 0;
        for (int j = 0; j < 3; j++) {
            sum += students[i].scores[j];
        }
        students[i].average = sum / 3.0;
    }
    
    // 打印学生成绩
    printf("
%-5s %-10s %-8s %-8s %-8s %-8s
", 
           "ID", "姓名", "成绩1", "成绩2", "成绩3", "平均分");
    printf("------------------------------------------------
");
    
    for (int i = 0; i < count; i++) {
        printf("%-5d %-10s %-8.1f %-8.1f %-8.1f %-8.1f
",
               students[i].id,
               students[i].name,
               students[i].scores[0],
               students[i].scores[1],
               students[i].scores[2],
               students[i].average);
    }
    
    // 查找最高分学生
    int maxIndex = 0;
    for (int i = 1; i < count; i++) {
        if (students[i].average > students[maxIndex].average) {
            maxIndex = i;
        }
    }
    
    printf("
最高分学生: %s (平均分: %.1f)
", 
           students[maxIndex].name, students[maxIndex].average);
    
    // 按平均分排序
    for (int i = 0; i < count-1; i++) {
        for (int j = 0; j < count-i-1; j++) {
            if (students[j].average < students[j+1].average) {
                Student temp = students[j];
                students[j] = students[j+1];
                students[j+1] = temp;
            }
        }
    }
    
    // 打印排序结果
    printf("
按平均分降序排列:
");
    printf("%-5s %-10s %-8s
", "ID", "姓名", "平均分");
    printf("-----------------------
");
    for (int i = 0; i < count; i++) {
        printf("%-5d %-10s %-8.1f
", 
               students[i].id, students[i].name, students[i].average);
    }
    
    // 统计分数分布
    int distribution[5] = {0}; // 0-59, 60-69, 70-79, 80-89, 90-100
    for (int i = 0; i < count; i++) {
        for (int j = 0; j < 3; j++) {
            int score = (int)students[i].scores[j];
            if (score < 60) distribution[0]++;
            else if (score < 70) distribution[1]++;
            else if (score < 80) distribution[2]++;
            else if (score < 90) distribution[3]++;
            else distribution[4]++;
        }
    }
    
    printf("
分数分布统计:
");
    printf("不及格(<60): %d
", distribution[0]);
    printf("及格(60-69): %d
", distribution[1]);
    printf("中等(70-79): %d
", distribution[2]);
    printf("良好(80-89): %d
", distribution[3]);
    printf("优秀(90-100): %d
", distribution[4]);
}

Step2:点击编辑器左上角运行按钮直接运行,Terminal窗口可以看到打印内容。

【数组与链表】数组的基本演绎法与排序“大乱斗”

打印内容文本显示:

=== 综合案例:学生成绩管理系统 ===

--- 学生成绩管理系统 ---

ID    姓名     成绩1  成绩2  成绩3  平均分
------------------------------------------------
1     张三     85.0     90.0     78.0     84.3    
2     李四     92.0     88.0     95.0     91.7    
3     王五     76.0     85.0     80.0     80.3    

最高分学生: 李四 (平均分: 91.7)

按平均分降序排列:
ID    姓名     平均分
-----------------------
2     李四     91.7    
1     张三     84.3    
3     王五     80.3    

分数分布统计:
不及格(<60): 0
及格(60-69): 0
中等(70-79): 2
良好(80-89): 4
优秀(90-100): 3

打印内容截图:

【数组与链表】数组的基本演绎法与排序“大乱斗”

至此,数组的基本演绎法与排序“大乱斗”案例已全部完成。

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
none
暂无评论...