一.实验内容
(1)插入排序与合并排序与快速排序运行时间与排序元素个数的统计比较;
(2)阐述比较结果。
(3)利用算法采用的设计方法,时间复杂度等分析得到该结果的原因。
二.实验过程及记录结果
1.插入排序代码:
void insertSort(int arr[], int n) {
int i, j, temp;
for (i = 1; i < n; i++) {
temp = arr[i];
for (j = i - 1; j >= 0 && arr[j] > temp; j--) {
arr[j + 1] = arr[j];
}
arr[j + 1] = temp;
}
}
2.合并排序代码:
void merge(int arr[], int left, int mid, int right) {
int i, j, k;
int n1 = mid - left + 1;
int n2 = right - mid;
int L[n1], R[n2];
for (i = 0; i < n1; i++) {
L[i] = arr[left + i];
}
for (j = 0; j < n2; j++) {
R[j] = arr[mid + 1 + j];
}
i = 0;
j = 0;
k = left;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
} else {
arr[k] = R[j];
j++;
}
k++;
}
while (i < n1) {
arr[k] = L[i];
i++;
k++;
}
while (j < n2) {
arr[k] = R[j];
j++;
k++;
}
}
void mergeSort(int arr[], int left, int right) {
if (left < right) {
int mid = left + (right - left) / 2;
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
merge(arr, left, mid, right);
}
}
快速排序代码:
void swap(int* a, int* b) {
int t = *a;
*a = *b;
*b = t;
}
int partition(int arr[], int low, int high) {
int pivot = arr[high];
int i = (low - 1);
for (int j = low; j <= high - 1; j++) {
if (arr[j] < pivot) {
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return (i + 1);
}
void quickSort(int arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
3.插入排序和合并排序排序n(0<n<1000)个数时间效率对比:
4.结果分析
实验结果:由运行结果可视化分析可以得出,当n逐渐增大后,直接插入排序所花费的时间明显高于合并排序和快速排序的时间。即当排序元素很多时,快速排序的时间效率最高,归并排序第二,直接插入排序的时间效率最差。
原因分析:
(1)合并排序
合并排序的时间复杂度为O(nlogn),其中n表示待排序序列的元素个数。这是由于在合并排序中,需要对元素进行多次比较和合并,每次合并都需要O(n)的时间复杂度。因此,随着待排序序列的元素个数的增加,所需时间也会按照O(nlogn)的规律增加。当n很大的时候,平均情况下,合并排序算法的比较次数小于0.25n次,因此效率也属于 θ(nlogn),并且由排序的过程来看,合并排序是稳定的,但是该算法需要牺牲额外的线性空间。
(2)直接插入排序:
直接插入排序的时间复杂度为O(n^2)。这是因为在每一趟操作中,都需要进行一次比较和一次移动操作。当待排序序列的元素个数增加时,所需的比较和移动次数也会按照O(n^2)的规律增加。插入排序最好的情况下是外部循环的每次迭代中只比较一次,即队升序排列的序列进行排序,此时的时间复杂度是O(n),而最坏的情况是对一个严格递减的序列进行排序此时的时间复杂度为O(n^2)。
(3)快速排序:
在平均情况下,每次分割得到的两个子区间的大小比例是1:1,即区间一分为二。这种情况下,递归的深度也是O(log n),但每次递归的时间复杂度为O(n),因此总的时间复杂度也是O(n log n)。如果每次分割选择的基准元素都是当前区间中间位置的元素,那么每次分割得到的两个子区间的大小比例是1:n-1。这种情况下,递归的深度同样是O(log n),但每次递归的时间复杂度为O(n),因此总的时间复杂度也是O(n log n)。
五.总结
快速排序和归并排序的时间效率在理论上是相同的,都是O(n log n)。而直接插入排序的时间效率在理论上是较低的,平均为O(n^2)。但在实际应用中,由于直接插入排序算法实现简单,对于小规模的数据排序效率较高,因此在某些情况下可能会比快速排序和归并排序更实用。