C++ 通过交换进行插入排序
我刚开始做DSA,有一个关于插入排序的问题 这是教科书/教程中的版本C++ 通过交换进行插入排序,c++,c,algorithm,sorting,C++,C,Algorithm,Sorting,我刚开始做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];
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;
}
}
交换代码:
void swap(int &a,int &b){
int temp = a;
a = b;
b = temp;
}
哦,如果有人能解释两者的时间复杂性,那就太棒了。你建议的替代方案不完整,你没有发布
swap()
的代码。在C中,<代码>交换< /代码>必须是宏,这样的宏很容易被篡改,而在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]);
}
}
}
void insertionSort(int A[],int n){
对于(int i=1;i0&&A[j]
在最坏的情况下,这两种方法的时间复杂度都是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 microseconds\n",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 microseconds\n",time_swap);
#包括
#包括
#包括
#包括
无效插入移位(int*arr,int n){
int i,j,k;
对于(i=1;i0&&arr[j-1]>temp;--j)
arr[j]=arr[j-1];
arr[j]=温度;
}
}
无效交换(int*a,int*b){
int temp=*a;
*a=*b;
*b=温度;
}
无效插入交换(int*arr,int n){
int i,j,k;
对于(i=1;i0&&arr[j-1]>temp;--j)
掉期(&arr[j-1],&arr[j]);
}
}
无效打印(整数*整数,整数n){
int i;
对于(i=0;它们都是O(n^2)。切换是一个很好的方法。切换涉及相当多的辅助剂(通过常数因子),因此这是一个重要的优化。与您的问题无关,但两个版本都会在a[]之前取消对内存的引用。temp第一次通过将具有j= i=0,并且引用[-1 ]。这可能不是你想要的。哦,我应该设置<代码> i=1 <代码>在外循环中,我猜“代码>我刚刚开始DSA < /Calp>???我使用<代码> SWAP-())/>代码>以C++作为参数(忘记提及)。。请将我链接到一个页面,其中解释了交换比移动慢,我真的很想阅读它。(或者解释一下)发布您的swap()的代码
函数。交换2个整数的方法有很多:大多数都涉及2次读取和2次写入,使用XCHG
指令的成本更高。相比之下,移位每一步只需一次读取和写入,最后只需一次写入。通常,评估代码效率的唯一方法是测量它!考虑到二次complexity,一个中等大小的数组将提供一个良好的基准。尝试不同的情况:排序、伪随机、逆序…良好的计时代码!我建议在基准之后打印这两个计时,以避免处理OUUT第一行显示的操作系统和插入\u交换()的计时之间的任何干扰
。还可以使用10000000000ll避免在具有32位时间的体系结构上出现整数溢出。\u t
。您还可以尝试在排序之前对不同的顺序进行基准测试,并使用伪随机数生成器更容易地适应各种数组大小。
#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 microseconds\n",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 microseconds\n",time_swap);