插入排序代码:
// 直接插入排序
void insertionSort1(int A[], int n) {
for (int i = 1; i < n; i++) {
int temp = A[i];
int j = i - 1;
while (j >= 0 && A[j] > temp) {
A[j + 1] = A[j];
j = j - 1;
}
A[j + 1] = temp;
}
}
插入排序结果(部分):
合并排序代码:
// 合并排序
void merge(int B[], int p, int C[], int q, int A[]) {
int i = 0, j = 0, k = 0;
while (i < p && j < q) {
if (B[i] <= C[j]) {
A[k] = B[i];
i++;
}
else {
A[k] = C[j];
j++;
}
k++;
}
while (i < p) {
A[k] = B[i];
i++;
k++;
}
while (j < q) {
A[k] = C[j];
j++;
k++;
}
}
void mergeSort(int A[], int n) {
if (n > 1) {
int mid = n / 2;
int* B = (int*)malloc(mid * sizeof(int)); // 动态分配内存给B
int* C = (int*)malloc((n - mid) * sizeof(int)); // 动态分配内存给C
for (int i = 0; i < mid; i++) {
B[i] = A[i];
}
for (int i = mid; i < n; i++) {
C[i - mid] = A[i];
}
mergeSort(B, mid);
mergeSort(C, n - mid);
merge(B, mid, C, n - mid, A);
free(B); // 释放B数组的内存
free(C); // 释放C数组的内存
}
}
合并排序结果(部分):
插入排序和合并排序排序n(0<n<5000)个数时间效率对比:
实验结果:由运行结果可视化分析可以得出,当n逐渐增大后,直接插入排序所花费的时间明显高于合并排序的时间。
原因分析:
1.合并排序
合并排序将待排序的数组不断地分割成小的数组,然后再合并这些小数组以得到最终的有序数组。使得整体的时间复杂度较低。其时间复杂度为O(n log n),因为每一次合并操作都涉及到n个元素,而总共需要进行log n次合并操作。
2.插入排序:
由于直接插入排序每次只能将一个元素插入到已排序序列中,因此在平均情况下需要进行n^2/4次比较和n^2/4次移动。假设要被排序的序列中由n个数,遍历一趟的时间复杂度为O(n),一共需要遍历n-1次所以插入排序的时间复杂度是O(N^2)。
下图是nlogn和n^2复杂度算法效率对比:
源码:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
// 直接插入排序
void insertionSort1(int A[], int n) {
for (int i = 1; i < n; i++) {
int temp = A[i];
int j = i - 1;
while (j >= 0 && A[j] > temp) {
A[j + 1] = A[j];
j = j - 1;
}
A[j + 1] = temp;
}
}
// 合并排序
void merge(int B[], int p, int C[], int q, int A[]) {
int i = 0, j = 0, k = 0;
while (i < p && j < q) {
if (B[i] <= C[j]) {
A[k] = B[i];
i++;
}
else {
A[k] = C[j];
j++;
}
k++;
}
while (i < p) {
A[k] = B[i];
i++;
k++;
}
while (j < q) {
A[k] = C[j];
j++;
k++;
}
}
void mergeSort(int A[], int n) {
if (n > 1) {
int mid = n / 2;
int* B = (int*)malloc(mid * sizeof(int)); // 动态分配内存给B
int* C = (int*)malloc((n - mid) * sizeof(int)); // 动态分配内存给C
for (int i = 0; i < mid; i++) {
B[i] = A[i];
}
for (int i = mid; i < n; i++) {
C[i - mid] = A[i];
}
mergeSort(B, mid);
mergeSort(C, n - mid);
merge(B, mid, C, n - mid, A);
free(B); // 释放B数组的内存
free(C); // 释放C数组的内存
}
}
int main() {
int size = 1000;
int* A = (int*)malloc(size * sizeof(int));
int* B = (int*)malloc(size * sizeof(int));
// 生成随机数组A和复制到数组B
for (int i = 0; i < size; i++) {
A[i] = rand();
B[i] = A[i];
}
clock_t start, end;
// 直接插入排序算法
printf("直接插入排序的运行时间:\n");
for (int j = 0; j < size; j++) {
start = clock();
insertionSort1(A, size);
end = clock();
printf("第%d个数的运行时间: %f 秒\n", j + 1, (double)(end - start) / CLOCKS_PER_SEC);
}
// 合并排序算法
printf("合并排序的运行时间:\n");
for (int j = 0; j < size; j++) {
start = clock();
mergeSort(B, size);
end = clock();
printf("第%d个数的运行时间: %f 秒\n", j + 1, (double)(end - start) / CLOCKS_PER_SEC);
}
free(A);
free(B);
return 0;
}