插入排序通过交换
Insertion Sort by swapping
我刚开始使用DSA,有一个关于插入排序的问题。
这是课本/教程的版本。
void insertion_sort(int A[], int n) {
for (int i = 0; i < n; i++) {
int temp = A[i];
int j = i;
while (temp < A[j - 1] && j > 0) {
A[j] = A[j - 1];
j = j - 1;
}
A[j] = temp;
}
}
我在想,如果我们使用swapping
数字而不是移动数字并将temp
值插入正确的孔位置,会有什么不同吗?
void insertionSort(int A[], int n) {
for (int i = 0; i < n; i++) {
int temp = A[i];
int j = i;
while (temp < A[j - 1] && j > 0) {
swap(A[j], A[j - 1]);
j--;
}
}
}
交换代码:
void swap(int &a,int &b){
int temp = a;
a = b;
b = temp;
}
哦,如果有人能解释这两者的时间复杂性,那就太棒了。
两种方法的时间复杂度在最坏情况下都是O(N^2)。但是,与第一种方法相比,第二种方法中的操作次数更多,因为第二种方法执行的交换次数与第一种方法中的移位次数相同,但是交换需要3次赋值,而基于移位的方法只需一次。因此,与仅仅移动元素相比,您提出的方法将会更慢。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
void insertion_shift(int* arr, int n){
int i,j,k;
for(i=1;i<n;++i){
int temp=arr[i];
for(j=i;j>0 && arr[j-1]>temp;--j)
arr[j]=arr[j-1];
arr[j]=temp;
}
}
void swap(int* a, int* b){
int temp= *a;
*a= *b;
*b= temp;
}
void insertion_swap(int* arr, int n){
int i,j,k;
for(i=1;i<n;++i){
int temp=arr[i];
for(j=i;j>0 && arr[j-1]>temp;--j)
swap(&arr[j-1],&arr[j]);
}
}
void print_arr(int* arr, int n){
int i;
for(i=0;i<n;++i)
printf("%d ",arr[i]);
printf("n");
}
int main(){
int n;
scanf("%d",&n);
int* arr1= (int*)malloc(sizeof(int)*n);
int* arr2= (int*)malloc(sizeof(int)*n);
int i;
for(i=0;i<n;++i){
scanf("%d",&arr1[i]);
arr2[i]=arr1[i];
}
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC_RAW,&start);
insertion_shift(arr1,n);
clock_gettime(CLOCK_MONOTONIC_RAW,&end);
uint64_t time_shift= (end.tv_sec - start.tv_sec)*1000000 +
(end.tv_nsec - start.tv_nsec)/1000;
printf("using shift: %lld microsecondsn",time_shift);
clock_gettime(CLOCK_MONOTONIC_RAW,&start);
insertion_swap(arr2,n);
clock_gettime(CLOCK_MONOTONIC_RAW,&end);
uint64_t time_swap= (end.tv_sec - start.tv_sec)*1000000 +
(end.tv_nsec - start.tv_nsec)/1000;
printf("using swap: %lld microsecondsn",time_swap);
}
下面是我在大小为10000的同一个数组上调用两个函数时得到的结果。10000个元素数组的编译和执行。如果仍然不相信,请尝试生成大小为1000-10000的随机数组,并运行上面的代码来观察差异。
您提出的替代方案不完整,您没有发布swap()
的代码。在C语言中,swap
必须是一个宏,这样的宏很容易出错,而在c++中,它可以是一个通过引用接受两个参数的函数。
A[j - 1]
之前,您应该测试j > 0
。如上所述,代码调用了未定义的行为。
关于你的问题,两个函数都同样慢,时间复杂度为O(N2),但第二个函数可能更慢,因为交换涉及更多的读写,而不是简单地将值移动一个位置,但在排序数组上可能更快,因为第一个版本有冗余存储。
请注意,您可以通过以下方式进一步简化代码:
void insertionSort(int A[], int n) {
for (int i = 1; i < n; i++) {
for (int j = i; j > 0 && A[j] < A[j - 1]; j--) {
swap(A[j], A[j - 1]);
}
}
}
相关文章:
- 这是插入排序的正确实现吗?
- 使用列表 STL 递归进行插入排序
- 列表 iter 不取消引用 使用列表进行插入排序
- 如何使插入排序更快?
- 插入排序的最小交换
- 双链表C++上的插入排序
- 如何在插入排序中使用 replace() 使语句变得不必要
- C++插入排序错误功能不起作用
- 如何在不通过插入排序更改原始矢量的情况下对 2D 矢量进行排序
- 插入排序打印错误的输出
- 从矢量末尾开始的插入排序
- 插入排序:我做错了什么?
- 插入排序的向量<unique_ptr<对时避免堆分配<>>>
- 获取有趣的输出以进行插入排序
- 插入排序算法在放入函数时的行为不同
- 插入排序的Valgrind Invalid读取尺寸8的尺寸
- 插入排序与插入/擦除?(所以我需要对一个向量进行排序,而不是手工做事,而是使用插入和擦除
- 堆排序和插入排序
- 计数Heapsort和插入排序中的复制和比较数
- 插入排序通过交换