#include "stdio.h"
// 函数声明
void print_array(int how_many, int data[], char *str);
void merge(int a[], int b[], int c[], int how_many);
void mergeSort(int key[], int how_many);
int main(void) {
const int SIZE = 8;
int a[SIZE] = {99, 82, 74, 85, 92, 67, 76, 49};
print_array(SIZE, a, "My grades\n"); // 调用print_many函数,打印合并排序前a数组的数据内容
printf("\n\n");
mergeSort(a, SIZE); // 调用mergesort函数
print_array(SIZE, a, "My sorted grades\n"); // 调用print_many函数,打印合并排序后a数组的数据内容
printf("\n\n");
return 0;
}
// 函数定义
void print_array(int how_many, int data[], char *str) {
int i = 0;
printf("%s", str); // 打印str指针指向的内容
for (i = 0; i < how_many; i++) {
printf("data[%d] = %d\t", i, data[i]); // 打印相关数组位置的数值
}
printf("\n");
}
/*使用当前合并函数的前提:被合并的a数组里面的元素和b数组里面的元素都是在自己的数组汇总已有排序。目前是按照从低到高进行排序的*/
void merge(int a[], int b[], int c[], int how_many) {
int i = 0, j = 0, k = 0;
// print_array(how_many, a, "合并前a:\n");
// print_array(how_many, b, "合并前b:\n");
// print_array(k, c, "合并前c:\n");
// printf("i = %d, j = %d, k = %d, how_many = %d\n\n", i, j, k, how_many);
/* 循环判断a数组和b数组的各个子项的值,并将小的数值优先放到c合并数组中*/
while (i < how_many && j < how_many) {
if (a[i] < b[j]) {
c[k++] = a[i++];
// print_array(how_many, a, "a1\n");
// print_array(k, c, "c1\n");
// printf("i = %d, j = %d, k = %d, how_many = %d\n\n", i, j, k, how_many);
} else {
c[k++] = b[j++];
// print_array(how_many, b, "b1\n");
// print_array(k, c, "c1\n");
// printf("i = %d, j = %d, k = %d, how_many = %d\n\n", i, j, k, how_many);
}
// print_array(how_many, a, "while1 a:\n");
// print_array(how_many, b, "while1 b:\n");
// print_array(k, c, "while1 c: \n");
// printf("i = %d, j = %d, k = %d, how_many = %d\n\n", i, j, k, how_many);
}
/* 当上述循环操作完成后,a数组的数组还未判断到最后一位,就将a数组中的元素通过while循环复制给c合并数组*/
while (i < how_many) {
c[k++] = a[i++];
// print_array(how_many, a, "a2\n");
// print_array(k, c, "c2\n");
// printf("i = %d, j = %d, k = %d, how_many = %d\n\n", i, j, k, how_many);
}
// print_array(how_many, a, "while2 a:\n");
// print_array(how_many, b, "while2 b:\n");
// print_array(k, c, "while2 c: \n");
// printf("i = %d, j = %d, k = %d, how_many = %d\n\n", i, j, k, how_many);
/* 当上述循环操作完成后,b数组的数组还未判断到最后一位,就将b数组中的元素通过while循环复制给c合并数组*/
while (j < how_many) {
c[k++] = b[j++];
// print_array(how_many, b, "b2\n");
// print_array(k, c, "c2\n");
// printf("i = %d, j = %d, k = %d, how_many = %d\n\n", i, j, k, how_many);
}
// print_array(how_many, a, "while3 a:\n");
// print_array(how_many, b, "while3 b:\n");
// print_array(k, c, "while3 c: \n");
// printf("i = %d, j = %d, k = %d, how_many = %d\n\n", i, j, k, how_many);
}
void mergeSort(int key[], int how_many) {
int j = 0, k = 1;
int w[how_many];
for (k = 1; k < how_many; k *= 2) { // 获取到合并数组的最大长度,目前是2的倍数
// print_array(how_many, key, "计算前1:");
// printf("j = %d, k = %d, how_many = %d", j, k, how_many);
// printf("\n");
for (j = 0; j < how_many - k; j += 2 * k) { // 获取到每次运算的子数组的最大长度,目前也是2的倍数,只是初始化为0
// print_array(how_many, key, "计算内前1:");
// printf("j = %d, k = %d, how_many = %d", j, k, how_many);
// printf("\n");
merge(key + j, key + j + k, w + j, k); // w数组作为key + j 和 key + j + k 的合并数组,k 为合并数组的最大长度;且w数组作为合并后的数据的接收方。且调取merge()函,并将相关的实参传递过期
// print_array(how_many, key, "计算内key1:");
// print_array(how_many, w, "计算内w1:");
// printf("j = %d, k = %d, how_many = %d", j, k, how_many);
// printf("\n");
}
/* 将w数组内的内容复制给key数组 */
for (j = 0; j < how_many; j++) {
key[j] = w[j]; // 将w数组内的内容复制给key数组
// print_array(how_many, key, "计算内key2:");
// print_array(how_many, w, "计算内w2:");
// printf("j = %d, k = %d, how_many = %d", j, k, how_many);
// printf("\n");
}
// print_array(how_many, key, "计算后key:");
// print_array(how_many, w, "计算后w:");
// printf("j = %d, k = %d, how_many = %d", j, k, how_many);
// printf("\n");
}
}
解释上述原理:
定义三个函数:
- void print_array(int how_many, int data[], char *str):无返回参数的print_array()函数,其中形式参数为:数组长度、int类型的数组指针data、字符指针str。函数的作用是打印字符指针指向的内容以及data指针指向的数组内的内容。
- void merge(int a[], int b[], int c[], int how_many):无返回参数的merge()函数,其中形式参数为:int类型的数组指针a、int类型的数组指针b、int类型的数组指针c、以及数组a和数组b的长度。函数的作用是将a数组和b数组内的内容进行从小到高排序并合并到数组c。
- void mergeSort(int key[], int how_many):无返回参数的mergeSort()函数,其中形式参数为:int类型的数组指针key、数组的长度。函数的作用是通过将key指针指向的数组,按照相关的逻辑将数组进行排序操作。