C++ 通过交换进行插入排序

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];

我刚开始做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;       
    }  
}
交换代码:

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);