计算数组中冒泡排序交换的数量,而不进行冒泡排序

时间:2015-12-30 20:20:35

标签: c++ arrays sorting

你好,我试图计算大小为N的数组中的bubblesort交换次数,但是我想这样做而不做Bubbleort,我听说过合并排序,有人已经告诉我它的某种合并排序修改...我不想使用这个基本算法>

void bubbleSort(int * array, int size){
    for(int i = 0; i < size - 1; i++){
        for(int j = 0; j < size - i - 1; j++){
            if(array[j+1] < array[j]){
                int tmp = array[j + 1];
                array[j + 1] = array[j];
                array[j] = tmp;
            }   
        }   
    }   
}  

你们中的任何人都有想法吗?

4 个答案:

答案 0 :(得分:3)

似乎您可以使用以下函数来计算掉期总数:

int calcSwaps(int *array, int size) {
    int cnt = 0;

    for (int i = 0; i + 1 < size; ++i) {
        for (int j = i + 1; j < size; ++j) {
            if (array[j] < array[i]) {
                ++cnt;
            }
        }
    }

    return cnt;
}

主要思想是,在这种类型的排序中,每个元素array[i]都将与所有元素array[j]j > iarray[j] < array[i]交换。

修改

我会尝试更仔细地解释它以避免误解。解决方案相当简单。考虑冒泡排序算法。让我们看一下初始未排序的数组。如果我们有array[i]元素,它会被交换多少次?好的,如果array[j],我们会交换元素array[j + 1]array[j] > array[j + 1]。根据所选择的排序算法,每两个元素最多可以交换一次。如果array[i] > array[j], i < j它们将被交换,因为我们想要最终获得一个排序数组。很容易看出,在这种情况下,我们只需要获取每个元素array[i],计算array[j], array[j] < array[i], j > i的数量(它将是将与之交换的元素数量) array[i]在排序过程中),最后将每个array[i]的所有这些数字相加得到答案。

答案 1 :(得分:1)

修改合并排序,以便除了对输入进行排序之外,还要计算该数组中的反转次数。让我们通过归纳证明它。

基本案例 容易 - 如果数组大小小于或等于1

,则返回0反转

一般情况: 让我们一步一步地分析问题。

我们要合并两个数组。那可能是什么样的倒置?反演(i,j)可能在同一半(左半部分或右半部分),或者我可能在左半部分,j可能在右半部分(我不能在右半部分,因为我们有约束我&lt; j)。然而,通过归纳假设,数组的左半部分和右半部分内的反转次数将通过对数组的每一半的相应递归调用返回,因此我们只需要计算两半的反转次数(我在左边,j在右边。)

我们如何计算左右阵列的反转次数?在合并排序的合并步骤中,我们给出了一个两个排序的数组(左和右)。对于左数组中左[i]的每个元素,我们想知道右数组中右边[j]的数量是否严格小于左数[i] 注意当我们将left [i]插入到合并数组中时,我们知道j左边的每个元素都小于left [i](因为它们在left [i]之前被插入到合并数组中)。因此,每次将left [i]插入到合并的数组中时,将计数器增加j。

#include <stdio.h>

long long int MS(int a[],int temp[],int left,int right);
long long int Merge(int a[],int temp[],int left,int mid,int right);

long long int MS(int a[],int temp[],int left,int right)
{
    long long int cnt=0;
    int mid;
    if(right>left)
    {
        mid=(right+left)/2;
        cnt=MS(a,temp,left,mid);
        cnt+=MS(a,temp,mid+1,right);
        cnt+=Merge(a,temp,left,mid+1,right);
    }
    return cnt;
}

long long int Merge(int a[],int temp[],int left,int mid,int right)
{
    int i,j,k;
    long long int cnt=0;
    i=left;
    j=mid;
    k=left;
    while(i<=mid-1 && j<=right)
    {
        if(a[i]<=a[j])
            temp[k++] = a[i++];
        else
        {
            temp[k++] = a[j++];
            cnt+=(mid-i);
        }
    }
    while (i<=mid-1)
        temp[k++]=a[i++];
    while(j<=right)
        temp[k++]=a[j++];
    for(i=left;i<=right;i++)
        a[i]=temp[i];
    return cnt;
}

int main()
{
    int *a,*tmp,t,n;
    scanf("%d",&t);
    for(int i=0;i<t;i++)
    {
        scanf("%d",&n);
        a=new int [n];
        tmp=new int [n];
        for(int j=0;j<n;j++)
            scanf("%d",&a[j]);
        printf("%lld\n",MS(a,tmp,0,n-1));
    }
    return 0;
}

答案 2 :(得分:0)

您可以按照三个简单的步骤操作。复制输入数组,然后在每次交换时递增计数器并返回该计数。有点像:

int bubbleSort(int * array, int size){
    std::vector<int> temp_array(array, array + size);
    int count{0};
    for(int i = 0; i < size - 1; i++){
        for(int j = 0; j < size - i - 1; j++){
            if(temp_array[j+1] < temp_array[j]){
                int tmp = temp_array[j + 1];
                temp_array[j + 1] = temp_array[j];
                temp_array[j] = tmp;
                count++;
            }
        }
    }
    return count;
}

答案 3 :(得分:0)

注意:It seems to work,但我不确定我的方法是否正确!

我们有一个示例数组:

{3, 5, 1, 4, 2}

找到最小元素index。要将其移动到数组的前缀,您需要index交换。在我的示例中,1是最小元素,1index 2是最小元素,因此需要2个互换才能将其放置在正确的位置。在那之后,我们有:

{1, 3, 5, 4, 2}

1现在位于正确的位置,因此我们可以专注于数组的其余部分以简化操作:

{3, 5, 4, 2}

代码:

#include <algorithm>
#include <vector>

unsigned swaps(std::vector<double>& data) {
    unsigned result = 0;
    while (!data.empty()) {
        auto smallest = std::min_element(data.begin(), data.end());
        result += smallest - data.begin();
        data.erase(smallest);
    }
    return result;
}

See it working (hopefully correctly) online