插入排序过程

时间:2018-06-26 15:33:34

标签: c algorithm insertion-sort

我一直在研究排序算法两天了。目前我正在做插入排序。所以一般的算法是:

void insertionSort(int N, int arr[]) {
    int i,j;
    int value;
    for(i=1;i<N;i++)
    {
        value=arr[i];
        j=i-1;
        while(j>=0 && value<arr[j])
        {
            arr[j+1]=arr[j];
            j=j-1;
        }
        arr[j+1]=value;
    }
    for(j=0;j<N;j++)
    {
        printf("%d ",arr[j]);
    }

    printf("\n");
}

现在我已经做到了:

void print_array(int arr_count, int* arr){
        int i;
        for (i=0;i<arr_count;i++){
                printf("%d ",arr[i]);
        }
        printf("\n");

    }

    void swap(int* m, int* n){
        int t = 0;
        t = *m;
        *m = *n;
        *n = t;
    }

    void insertionSort(int arr_count, int* arr) {
        int i, j;

        for(i = 0;i<arr_count;i++){
            for (j=0;j<i;j++){
                if (arr[i] < arr[j]){
                    swap(arr+i, arr+j); 
                  }
            }
            //if (i!=0)
            //print_array(arr_count, arr);
        }

    print_array(arr_count, arr);
    }

现在,我的问题是我的自定义方法与传统方法之间的区别是什么。两者都具有N 2 的复杂度。...
请帮忙..
预先感谢

2 个答案:

答案 0 :(得分:1)

在每次迭代中,您提供的原始代码通过循环移动元素将每个元素移动到位。对于 n 个元素周期,涉及到 n +1个分配。

可以通过成对交换而不是较大周期移动元素来实现插入排序。实际上,有时以这种方式进行教导。这是可能的,因为任何排列(不仅是周期)都可以表示为一系列交换。通过交换实现 n 元素周期需要 n -1交换,并且每个交换(为2元素周期)需要2 + 1 = 3分配。然后,对于大于两个元素的循环,使用成对交换的方法会做更多的工作,将比例缩放为3 *( n -1)而不是 n +1。但是,这不会改变渐近复杂度,正如您所看到的, n 的指数不变。

但是请注意原始代码和您的代码之间的另一个主要区别:原始代码在列表中向后扫描向后以查找插入位置,而您向后扫描向前。无论使用成对交换还是更大的周期,向后扫描都具有可以随需进行所需重新排序的优点,因此一旦找到插入位置,就可以完成。这是使插入排序在比较排序中如此出色的原因之一,以及为什么它对于最初几乎被排序的输入而言特别快。

向前扫描意味着一旦找到插入位置,就只能开始。您然后必须循环这些元素。结果,您的方法会在每次迭代时检查排序后的数组头中的每个元素。此外,当它实际执行重新排序时,它会执行许多不必要的比较。取而代之的是,它可以使用列表的开头开始进行排序的知识,而无需执行任何比较就可以执行循环(任一种方式)。额外的比较掩盖了这样的事实,即代码只是在此时执行了适当的元素循环(意识到了吗?),这可能就是为什么有人将您的实现误认为是冒泡排序的原因。

从技术上来说,您仍然是一个插入排序,但是该实现没有利用抽象插入排序算法的特征,该算法使编写良好的实现比其他类型的实现更具优势渐近复杂度。

答案 1 :(得分:1)

插入排序算法和自定义算法之间的主要区别是处理的方向。插入排序算法是将范围内较小的元素一一向左移动,而算法是将范围较大的元素一一向左移动。范围在右侧。

另一个关键的区别是在最佳情况下插入排序和算法的时间复杂度。 如果值