简介:本篇文章主要介绍了一维数组,二维数组,字符数组的定义,数组的应用,数组的核心代码解析,适用于0基础的初学者.
-
C语言数组
-
1.一维数组
-
1.1定义
-
1.1.1声明
- 语法:数据类型 数组名[数组大小];
- 示例:int arr[5];
-
1.1.2初始化
-
a.静态初始化
- 完全初始化:int arr[5] = {1, 2, 3, 4, 5};
- 部分初始化:int arr[5] = {1, 2};(剩余元素初始化为0)
- 特殊初始化:int arr[] = {1, 2, 3, 4, 5};(编译器自动计算大小)
-
b.动态初始化
-
使用malloc
- int *arr = (int *)malloc(5 * sizeof(int));
- for (int i = 0; i < 5; i++) { arr[i] = i + 1; }
-
使用calloc
- int *arr = (int *)calloc(5, sizeof(int));
- for (int i = 0; i < 5; i++) { arr[i] = i + 1; }
-
使用malloc
-
a.静态初始化
-
1.1.1声明
-
1.2一维数组访问
-
1.2.1通过索引访问
- 语法:数组名[索引]
- 示例:int value = arr[0];
-
1.2.2边界检查
- if (index >= 0 && index < n) { int value = arr[index]; }
-
1.2.1通过索引访问
-
1.3一维数组操作
-
1.3.1遍历数组
- 使用for循环;
- for (int i = 0; i < 数组大小; i++) { printf("%d ", arr[i]);}
-
1.3.2数组排序
-
a.选择排序
- for (int i = 0; i < 数组大小 - 1; i++) { int minIndex = i; for (int j = i + 1; j < 数组大小; j++) { if (arr[j] < arr[minIndex]) { minIndex = j; } } int temp = arr[minIndex]; arr[minIndex] = arr[i]; arr[i] = temp;}
-
b.冒泡排序
- for (int i = 0; i < 数组大小 - 1; i++) { for (int j = 0; j < 数组大小 - i - 1; j++) { if (arr[j] > arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } }}
-
a.选择排序
-
1.3.3数组搜索
-
a.线性搜索
- int search(int arr[], int 数组大小, int key) { for (int i = 0; i < 数组大小; i++) { if (arr[i] == key) { return i; } } return -1;}
-
b.二分搜索
- int binarySearch(int arr[], int 数组大小, int key) { int left = 0, right = 数组大小 - 1; while (left <= right) { int mid = left + (right - left) / 2; if (arr[mid] == key) { return mid; } if (arr[mid] < key) { left = mid + 1; } else { right = mid - 1; } } return -1;}
-
a.线性搜索
-
1.3.4数组长度
- 使用sizeof运算符计算
- int length = sizeof(numbers) / sizeof(numbers[0]);
-
1.3.1遍历数组
-
1.4数组与指针
- 1.4.1数组名作为指针:数组名是指向数组第一个元素的常量指针:int *ptr = arr;
- 1.4.2指针运算:移动到下一个元素:ptr++;
- 1.4.3指针与数组的关系:*(arr + i)等价于arr[i]
-
1.5数组作为函数参数
- 1.5.1传递一维数组:函数声明:void func(int arr[], int 数组大小);函数调用:int arr[5] = {1, 2, 3, 4, 5}; func(arr, 5);
-
1.1定义
-
2.二维数组
-
2.1定义
-
2.1.1声明
- 数据类型 数组名[行数][列数];
- 示例:int arr[3][4];
-
2.1.2初始化
- 完全初始化:int arr[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
- 部分初始化:int arr[3][4] = { {1, 2}, {5, 6}, {9, 10}};(剩余元素初始化为0)
- 特殊初始化:int arr[][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};(编译器自动计算行数)
-
2.1.1声明
-
2.2访问
- 2.2.1通过索引访问:int value = arr[行索引][列索引];
- 2.2.2示例:int value = arr[1][2][3];
-
2.3操作
-
2.3.1遍历二维数组
- 使用嵌套for循环:
- for (int i = 0; i < 行数; i++) { for (int j = 0; j < 列数; j++) { printf("%d ", arr[i][j]); } printf("\n");}
-
2.3.1遍历二维数组
-
2.4二维数组与指针
- 2.4.1数组名作为指针:int (*ptr)[列数] = arr;
- 2.4.2指针运算:ptr++;(移动到下一行)
- 2.4.3指针与数组的关系:*(*(arr + i) + j)等价于arr[i][j]
-
2.5二维数组作为函数参数
- 2.5.1传递二维数组:函数声明:void func(int arr[][列数], int 行数);函数调用:int arr[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}; func(arr, 3);
-
2.1定义
-
3.字符数组
-
3.1定义
-
3.1.1声明
- 语法:char 数组名[数组大小];
- 示例:char str[10];
-
3.1.2初始化
-
a.字符初始化
-
a.1完全初始化
- 定义:初始化数组长度所有的值
- char str[5] = {'H', 'e', 'l', 'l', 'o',}; //长度为5
-
a.2部分初始化
- 定义:初始化元素的个数,小于数组的长度,没有初始化部分使用'\0'补齐
- char str[10] = {'H', 'e', 'l', 'l', 'o'}; //剩余元素初始化为'\0')
-
a.3特殊初始化
- 定义:不定义数组的长度,由初始化元素的个数来决定
- char str[ ] = {'H', 'e', 'l', 'l', 'o'}; //长度为5
-
a.1完全初始化
-
b.字符串初始化
-
b.1完全初始化
- 定义:初始化数组长度所有的值
- char str[6] = {"hello"}; //长度为6,最后一位是补'\0'
- char str[6] = "hello"; //长度为6,最后一位是补'\0'
-
b.2部分初始化
- 定义:初始化元素的个数,小于数组的长度,没有初始化部分使用'\0'补齐
- char str[4] = {"hi"}; //剩余元素初始化为'\0')
-
b.3特殊初始化
- 定义:不定义数组的长度,由初始化元素的个数来决定
- char str[ ] = {"hello"}; //长度为6
-
b.1完全初始化
-
a.字符初始化
-
3.1.1声明
-
3.2访问
-
3.2.1通过索引访问
- 字符数组中的每个字符都可以通过其索引进行访问。索引从0开始,最后一个字符的索引是length - 1,其中length是字符串的长度。char str[] = "Hello";printf("First character: %c\n", str[0]); // 输出 'H'printf("Last character: %c\n", str[4]); // 输出 'o'
-
3.2.2使用指针访问
- 字符数组的名称可以作为指向数组首元素的指针来使用。可以通过指针运算来访问字符数组中的各个字符。char str[] = "Hello";char *ptr = str;printf("First character: %c\n", *ptr); // 输出 'H'printf("Second character: %c\n", *(ptr + 1)); // 输出 'e'// 使用循环遍历字符数组while (*ptr != '\0') { printf("%c", *ptr); ptr++;}printf("\n");
-
3.3.3边界检查
- 为了避免越界访问,应该始终进行边界检查,确保索引在合法范围内。char str[] = "Hello";int length = strlen(str);int index = 2;if (index >= 0 && index < length) { printf("Character at index %d: %c\n", index, str[index]);} else { printf("Index out of bounds\n");}
-
3.2.4遍历字符数组
- 使用for循环或while循环来遍历字符数组,直到遇到字符串结束符\0。char str[] = "Hello";int length = strlen(str);for (int i = 0; i < length; i++) { printf("%c", str[i]);}printf("\n");
- 使用while循环char str[] = "Hello";char *ptr = str;while (*ptr != '\0') { printf("%c", *ptr); ptr++;}printf("\n");
-
3.3.5二维字符数组
- 可以通过多个索引来访问每个字符。char strArray[3][6] = {"Hello", "World", "C"};// 访问第一个字符串的第一个字符printf("out %c\n", strArray[0][0]);// 遍历所有字符串并输出for (int i = 0; i < 3; i++) { for (int j = 0; j < 6 && strArray[i][j] != '\0'; j++) { printf("%c", strArray[i][j]); } printf("\n");}
-
3.3.6动态内存分配的数组
- 对于使用malloc或calloc动态分配的字符数组,同样可以通过索引或指针进行访问,但需要注意内存管理,使用完后要释放内存。#include <stdio.h>#include <stdlib.h>#include <string.h>int main() { char *str = (char *)malloc(6 * sizeof(char)); strcpy(str, "Hello"); // 通过索引访问 printf("First character: %c\n", str[0]); // 通过指针访问 char *ptr = str; while (*ptr != '\0') { printf("%c", *ptr); ptr++; } printf("\n"); free(str); // 释放动态分配的内存 return 0;}
-
3.2.1通过索引访问
-
3.3字符数组操作
-
3.3.1字符及字符串输入
-
scanf
- int scanf(const char *format, ...):从标准输入读取格式化输入。
- char str[100];scanf("%s", str); // 读取一个单词(遇到空格、换行或制表符停止)
-
fscanf
- int fscanf(FILE *stream, const char *format, ...):从指定文件流读取格式化输入。
-
fgets
- char *fgets(char *str, int n, FILE *stream):从指定文件流读取最多n-1个字符,直到遇到换行符或EOF。自动添加\0作为字符串结束符。
- char str[100];fgets(str, sizeof(str), stdin); // 读取一行字符串
-
getline(非标准)
- ssize_t getline(char **lineptr, size_t *n, FILE *stream):动态分配内存读取一行字符串。适用于不确定长度的输入。
- char *line = NULL;size_t len = 0;ssize_t read = getline(&line, &len, stdin);if (read != -1) { printf("Read line: %s", line); free(line);}
-
gets(不推荐)
- char *gets(char *str):从标准输入读取一行字符串,直到遇到换行符或EOF。由于不检查缓冲区溢出,存在安全风险,已被弃用。
-
scanf
-
3.3.2字符及字符串输出
-
printf
- int printf(const char *format, ...):向标准输出写入格式化输出。
- char str[] = "Hello, World!";printf("%s\n", str); // 输出字符串
-
fprintf
- int fprintf(FILE *stream, const char *format, ...):向指定文件流写入格式化输出。
-
puts
- int puts(const char *str):将字符串str和一个换行符写入标准输出。
- char str[] = "Hello, World!";puts(str); // 输出字符串并换行
-
fputs
- int fputs(const char *str, FILE *stream):将字符串str写入指定文件流,不添加换行符。
- char str[] = "Hello, World!";fputs(str, stdout); // 输出字符串,不换行
-
sprintf
- int sprintf(char *str, const char *format, ...):将格式化数据写入字符串str。
- char buffer[50];sprintf(buffer, "Value: %d", 42); // 格式化输出到字符串printf("%s\n", buffer);
-
snprintf
- int snprintf(char *str, size_t size, const char *format, ...):将格式化数据写入字符串str,最多写入size-1个字符,确保以\0结尾。
- snprintf(buffer, sizeof(buffer), "Value: %d", 42); // 安全的格式化输出printf("%s\n", buffer);
-
printf
-
3.3.3字符处理函数<ctype.h> 库
-
字符检查函数
- isalnum(c):检查字符c是否为字母或数字。
- isalpha(c):检查字符c是否为字母(包括大写和小写字母)。
- iscntrl(c):检查字符c是否为控制字符。
- isdigit(c):检查字符c是否为数字(0-9)。
- isgraph(c):检查字符c是否为图形字符(非空字符,不包括空格)。
- islower(c):检查字符c是否为小写字母。
- isprint(c):检查字符c是否为可打印字符(包括空格)。
- ispunct(c):检查字符c是否为标点符号。
- isspace(c):检查字符c是否为空白字符(如空格、制表符、换行符等)。
- isupper(c):检查字符c是否为大写字母。
- isxdigit(c):检查字符c是否为十六进制数字(0-9, a-f, A-F)。
-
字符转换函数
- tolower(c):将字符c转换为小写,如果不是大写字母则保持不变。
- toupper(c):将字符c转换为大写,如果不是小写字母则保持不变。
-
字符检查函数
-
3.3.4字符串处理函数<string.h> 库
-
a.字符串操作
- a1.计算字符串长度strlen(s):计算字符串s的长度,不包括结尾的\0。size_t len = strlen("Hello, World!");
-
a2.复制字符串
- strcpy(dest, src):将字符串src复制到dest,包括结尾的\0。char dest[50];strcpy(dest, "Hello, World!");
- strncpy(dest, src, n):最多复制src的前n个字符到dest,如果src长度小于n,则用\0填充剩余部分。char dest[50];strncpy(dest, "Hello, World!", 5);dest[5] = '\0'; // 保证字符串以'\0'结尾
-
a3.连接字符串
- strcat(dest, src):将字符串src连接到dest的末尾,覆盖dest原有的结尾\0。char dest[50] = "Hello, ";strcat(dest, "World!");
- strncat(dest, src, n):最多将src的前n个字符连接到dest的末尾。char dest[50] = "Hello, ";strncat(dest, "World!", 5);
-
b.字符串比较
-
b1.比较两个字符串
- strcmp(s1, s2):比较两个字符串s1和s2,返回值为0表示相等,负数表示s1小于s2,正数表示s1大于s2。int result = strcmp("apple", "banana");
- strncmp(s1, s2, n):最多比较两个字符串的前n个字符。int result = strncmp("apple", "apples", 5);
-
b2.忽略大小写比较
- strcasecmp(s1, s2):忽略大小写比较两个字符串(非标准,但广泛支持)。int result = strcasecmp("Apple", "apple");
- strncasecmp(s1, s2, n):忽略大小写最多比较两个字符串的前n个字符(非标准,但广泛支持)。int result = strncasecmp("Apple", "apple", 5);
-
b1.比较两个字符串
-
c.字符串查找与替换
-
c1.查找字符
- strchr(s, c):在字符串s中查找字符c第一次出现的位置,返回指向该位置的指针,未找到则返回NULL。
- strrchr(s, c):在字符串s中查找字符c最后一次出现的位置,返回指向该位置的指针,未找到则返回NULL。char *ptr = strrchr("Hello, World!", 'o');
- c2.查找子串strstr(s1, s2):在字符串s1中查找子串s2第一次出现的位置,返回指向该位置的指针,未找到则返回NULL。char *ptr = strstr("Hello, World!", "World");
- c3.分割字符串char *strtok(char *str, const char *delim):strtok(s, delim):将字符串s按分隔符delim分割成多个子串,每次调用返回一个子串,直到没有更多子串时返回NULL。
-
c1.查找字符
-
d.内存操作
- d1.内存复制void *memcpy(void *dest, const void *src, size_t n):从src复制n个字节到dest。void *memmove(void *dest, const void *src, size_t n):与memcpy类似,但处理重叠内存区域更安全。
- d2.内存设置void *memset(void *s, int c, size_t n):将n个字节的内容设置为字符c。
-
e.字符串转换.
- e1.字符串转整数int atoi(const char *s):将字符串s转换为整数。long atol(const char *s):将字符串s转换为长整数。long long atoll(const char *s):将字符串s转换为长整数(64位)。
- e2.字符串转浮点数double atof(const char *s):将字符串s转换为双精度浮点数。
- e3.格式化输入输出int sprintf(char *str, const char *format, ...):按照格式化字符串format将数据写入字符串str。int sscanf(const char *str, const char *format, ...):从字符串str中读取数据,并根据格式化字符串format解析到参数中。
-
a.字符串操作
-
3.3.1字符及字符串输入
-
3.4字符数组与指针
-
3.4.1字符数组与指针的定义
- 字符数组的名称实际上是一个指向数组首元素的常量指针。可以使用数组名来访问数组中的元素,就像使用指针一样。
- char str[] = "Hello";printf("First character: %c\n", *str); // 输出 'H'str 是一个指向字符数组首元素的指针。*str 解引用指针,获取第一个字符。
-
3.4.2指针赋值与字符数组
- 可以通过指针变量指向字符数组,并使用指针运算来遍历或修改字符数组中的内容。
-
char str[] = "Hello";char *ptr = str;// 使用指针遍历字符数组while (*ptr != '\0') { printf("%c", *ptr); ptr++;}printf("\n");
- ptr 指向字符数组的首元素。
- *ptr 访问当前指针指向的字符。
- ptr++ 移动指针到下一个字符。
-
3.4.3指针算术与字符数组
- 指针算术允许你通过指针偏移量来访问字符数组中的任意元素。
- char str[] = "Hello";
- char *ptr = str;
- printf("Second character: %c\n", *(ptr + 1)); // 输出 'e'
- *(ptr + 1) 访问指针指向位置后一个字符。
-
3.4.4使用动态分配字符数组
- 使用malloc或calloc动态分配字符数组时,返回的是一个指向字符数组的指针。
- #include <stdio.h>#include <stdlib.h>#include <string.h>int main() { char *str = (char *)malloc(6 * sizeof(char)); strcpy(str, "Hello"); // 使用指针访问动态分配的字符数组 printf("First character: %c\n", *str); // 使用循环遍历字符数组 for (int i = 0; i < 5; i++) { printf("%c", str[i]); } printf("\n"); free(str); // 释放动态分配的内存 return 0;}
-
3.4.5字符串字面量与指针
- 字符串字面量(如 "Hello")实际上是存储在只读内存区域中的字符数组,使用时会返回一个指向该区域的指针。
- char *str = "Hello"; // str 指向字符串字面量printf("First character: %c\n", *str); // 输出 'H'// 注意:不能修改字符串字面量的内容// *str = 'h'; // 这将导致未定义行为
-
3.4.6多维字符数组与指针
- 对于多维字符数组(如二维字符数组),可以通过多个指针来访问每个字符。
- char strArray[3][6] = {"Hello", "World", "C"};// 使用指针访问多维字符数组for (int i = 0; i < 3; i++) { char *ptr = strArray[i]; while (*ptr != '\0') { printf("%c", *ptr); ptr++; } printf("\n");}
-
3.4.7 指针与数组的关系总结
- 数组名是常量指针:数组名等价于指向数组首元素的指针,但不能修改数组名本身。
- 指针算术:可以使用指针算术(如ptr + n)来访问数组中的任意元素。
- 解引用指针:使用*ptr可以访问指针所指向的字符。
- 动态分配:动态分配的字符数组通过指针进行访问和操作,记得释放内存。
- 字符串字面量:字符串字面量是只读的,不能修改其内容。
-
3.4.1字符数组与指针的定义
-
3.5字符数组作为函数参数
-
3.5.1定义
- 当将字符数组作为参数传递给函数时,实际上是传递了一个指向数组首元素的指针。
-
3.5.2传递字符数组声明调用
- 函数声明:void func(char str[]);
- 函数调用:char str[100] = "Hello"; func(str);
-
3.5.3函数实现
- void printString(char *str) { while (*str != '\0') { putchar(*str++); } putchar('\n');}int main() { char str[] = "Hello"; printString(str); // 传递字符数组的指针 return 0;}
-
3.5.1定义
-
3.1定义
-
4.思维导图
- 根据思维导图,能够了解所要学习数组所有核心点的知识
5.数组核心代码
5.1数组声明与定义
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
// 一维数组声明与静态初始化
int arr1[5];
int arr2[5] = {1, 2, 3, 4, 5};
// 二维数组声明与静态初始化
int arr3[3][4];
int arr4[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8},{9, 10, 11, 12}};
// 动态数组(使用malloc)
int *arr5 = (int *)malloc(5 * sizeof(int));
if (arr5 == NULL)
{
// 内存分配失败处理
perror("Memory allocation failed");
exit(EXIT_FAILURE);
}
for (int i = 0; i < 5; i++)
{
arr5[i] = i + 1;
}
// 打印一维数组 arr2
printf("一维数组 arr2: ");
for (int i = 0; i < 5; i++)
{
printf("%d ", arr2[i]);
}
printf("\n");
// 打印二维数组 arr4
printf("二维数组 arr4:\n");
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
printf("%d ", arr4[i][j]);
}
printf("\n");
}
// 打印动态数组 arr5
printf("动态数组 arr5: ");
for (int i = 0; i < 5; i++)
{
printf("%d ", arr5[i]);
}
printf("\n");
// 释放动态分配的内存
free(arr5);
return 0;
}
5.2数组的访问
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
// 一维数组声明与静态初始化
int arr2[5] = {1, 2, 3, 4, 5};
// 二维数组声明与静态初始化
int arr4[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// 访问一维数组第一个元素
int value1 = arr2[0];
printf("Value1 (arr2[0]): %d\n", value1);
// 访问二维数组第二行第三列元素
int value2 = arr4[1][2];
printf("Value2 (arr4[1][2]): %d\n", value2);
// 边界检查示例
int index = 3;
if (index >= 0 && index < 5)
{
int value3 = arr2[index];
printf("Value3 (arr2[%d]): %d\n", index, value3);
} else {
printf("Index out of bounds\n");
}
// 测试超出范围的索引
index = 5;
if (index >= 0 && index < 5) {
int value3 = arr2[index];
printf("Value3 (arr2[%d]): %d\n", index, value3);
} else {
printf("Index out of bounds\n");
}
return 0;
}
5.3数组的遍历
#include <stdio.h>
int main(int argc, const char *argv[])
{
// 一维数组声明与静态初始化
int arr2[5] = {1, 2, 3, 4, 5};
// 二维数组声明与静态初始化
int arr4[3][4] = {
{1, 2, 3, 4}, {5, 6, 7, 8},{9, 10, 11, 12}};
// 遍历一维数组
printf("一维数组 arr2: ");
for (int i = 0; i < 5; i++)
{
printf("%d ", arr2[i]);
}
printf("\n");
// 遍历二维数组
printf("二维数组 arr4:\n");
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
printf("%d ", arr4[i][j]);
}
printf("\n");
}
return 0;
}
/*一维数组:
arr2 初始化为 {1, 2, 3, 4, 5}。
使用单层 for 循环遍历并打印每个元素。
二维数组:
arr4 初始化为指定的二维数组。
使用嵌套的 for 循环遍历并打印每个元素,每行结束后打印换行符。
通过这个示例代码,你可以更好地理解C语言数组的遍历方法。
*/
5.4数组的排序
5.4.1冒泡排序
a.冒泡排序的原理:依次比较相邻的元素,如果前面的比后面的大(小)就进行交换每一趟比较后,就会得到一个最大值(小),该值不进行下一轮的比较对剩余的部分,再次进行前面的操作,直到剩余一个元素为止,排序成功。
天蓝色:待排序
绿色:正在比较的数组元素
橙色:已经拍好的数组元素
b.冒泡排序的要素
b1.需要双重循环来解决:
外层循环:控制遍历的次数。总共需要 n-1 次遍历。
i 从 0 到 n-2。
内层循环:比较相邻的元素并交换它们。
j 从 0 到 n-i-2。
b2.每趟的比较次数 +所在趟数 == 元素总个数.
b3.每次内层循环结束后,最大的元素会被“冒泡”到数组的末尾。
b4.比较和交换:
如果 arr[j] 大于 arr[j + 1],则交换这两个元素。
使用临时变量 temp 来交换元素的值。
#include <stdio.h>
int main(int argc, const char *argv[])
{
int arr[] = {64, 25, 12, 22, 11};
int n = sizeof(arr) / sizeof(arr[0]);
int i, j, temp;
printf("原始数组: \n");
for (i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
// 冒泡排序算法
for (i = 0; i < n - 1; i++)
{
for (j = 0; j < n - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
// 交换 arr[j] 和 arr[j + 1]
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
printf("冒泡排序后的数组: \n");
for (i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
5.4.2选择排序
a.选择排序的原理:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
b.选择排序的算法
b1.外层循环 for (int i = 0; i < n - 1; i++)
遍历数组中的每个元素,i
表示当前考虑的元素位置。
b2.内层循环 for (int j = i + 1; j < n; j++)
从当前元素的下一个元素开始遍历,寻找从 i
开始的最小元素。
b3.如果在内层循环中发现比当前最小值更小的元素,则更新最小值的索引 minIndex
。
b4.内层循环结束后,如果 minIndex
不等于 i
,则交换 arr[i]
和 arr[minIndex]
。
c.选择排序注意:选择排序的时间复杂度为O(n^2),其中n是数组的长度。它不是一种高效的排序算法,但它的实现简单,对于小型数据集来说足够使用。对于大型数据集,通常会使用更高效的排序算法,如快速排序、归并排序或堆排序。
#include <stdio.h>
int main(int argc, const char *argv[])
{
int arr[] = {64, 25, 12, 22, 11}; // 待排序数组
int n = sizeof(arr) / sizeof(arr[0]); // 计算数组长度
// 外层循环,遍历数组中的每个元素
for (int i = 0; i < n - 1; i++)
{
// 假设当前元素为最小值
int minIndex = i;
// 内层循环,从当前元素的下一个元素开始遍历,寻找最小值
for (int j = i + 1; j < n; j++)
{
// 如果找到更小的元素,则更新最小值的索引
if (arr[j] < arr[minIndex])
{
minIndex = j;
}
}
// 如果最小值不是当前元素,则交换它们
if (minIndex != i)
{
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
// 打印排序后的数组
printf("排序后的数组: ");
for (int i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
5.4.3插入排序
是一种简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。在C语言中,插入排序的实现通常涉及到数组的操作。
a.插入排序的原理
a1.初始状态: 假设数组的第一个元素已经是有序的(因为一个元素本身就是有序的)。
a2.排序过程:
从数组的第二个元素开始,依次将每个元素插入到前面已经排好序的子数组中。
对于每个待插入的元素,从后向前比较它与已排序子数组中的元素。
如果待插入元素小于已排序子数组中的某个元素,则将该元素向后移动一位,为待插入元素腾出位置。
重复这个过程,直到找到合适的位置插入待插入元素。
a3.重复步骤2: 继续处理数组中的下一个元素,直到整个数组都被排序。
b.插入排序的算法
b1.外层循环 for (int i = 1; i < n; i++)
从数组的第二个元素开始遍历,因为第一个元素默认是已排序的。
b2.int key = arr[i];
保存当前要插入的元素。
b3.int j = i - 1;
初始化一个指针,指向当前元素的前一个位置。
b4.内层循环 while (j >= 0 && arr[j] > key)
将大于 key
的元素向后移动一位,直到找到 key
应该插入的位置。
b5..arr[j + 1] = key;
将 key
插入到正确的位置。
#include <stdio.h>
int main(int argc, const char *argv[])
{
int arr[] = {12, 11, 13, 5, 6}; // 待排序数组
int n = sizeof(arr) / sizeof(arr[0]); // 计算数组长度
// 插入排序算法
for (int i = 1; i < n; i++)
{
int key = arr[i]; // 当前要插入的元素
int j = i - 1;
// 将大于key的元素向后移动一位
while (j >= 0 && arr[j] > key)
{
arr[j + 1] = arr[j];
j--;
}
// 插入key到正确的位置
arr[j + 1] = key;
}
// 打印排序后的数组
printf("排序后的数组: ");
for (int i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
6.数组练习题