简体   繁体   English

C-合并排序的合并部分

[英]C - merge part of merge sort

I am new to merge sorts and am trying to create one. 我是新来的合并类别,正在尝试创建一个类别。 My merge sort is not sorting the array I am sending it and I can't figure out why. 我的合并排序不是对发送的数组进行排序,我也不知道为什么。 here is a link to all of the code http://pastebin.com/M4RUzhUa 这是所有代码的链接http://pastebin.com/M4RUzhUa

Here is my mergesort function 这是我的mergesort函数

void merge_sort(int array[], int low, int high) {
        int middle = (low + high) / 2;

        if(low < high) {
                merge_sort(array, low, middle);
                merge_sort(array, middle+1, high);
                merge(array, low, middle, high);
        }
}

Here is my (updated) merge function 这是我的(更新)合并功能

void merge(int array[], int low, int middle, int high) {
int size,left,right,i, j;
size = high - low + 1;
int array1[high];

left = low;
right = middle + 1;
i = low;

while ((left<=middle) && (right<=high)) {
        if(array[left] < array[right]) {
                array1[i] = array[left];
                left++;
                i++;
        }
        else {
                array1[i] = array[right];
                right++;
                i++;
        }
}
while (left <= middle) {
        array1[i] = array[left];
        left++;
        i++;
}
while (right <= high) {
        array1[i] = array[right];
        right++;
        i++;
}
for (j = low; j < i; j++) {
        array[j] = array1[j];
}
}

In my program the input array is 在我的程序中,输入数组是

9 3 2 1 5 9 3 2 1 5

and the output is 输出是

0 1 2 3 5 0 1 2 3 5

something is happening with the first element that i can't figure out 我无法弄清楚的第一个元素正在发生某些事情

New comments for updated code: 更新代码的新注释:

It looks like you are waltzing past the end of your array. 看起来您正在犹豫不决地走过阵列的尽头。 A way to test that would be to add some guard variables around your array, like this: 一种测试方法是在数组周围添加一些保护变量,如下所示:

#define NUM_OF_INTS 5
#define DEBUG 1
int main()
{
    int frontguard=-500;
    int numbers[NUM_OF_INTS];
    int backguard=-600;
    int i;

    srand(0);
    //Fill the array
    for( i = 0; i < NUM_OF_INTS; i++ )
    {
        //Use random numbers
        //numbers[i] = rand()%10000;    

        //Use reverse sorted list
        numbers[i] = NUM_OF_INTS-i;         

        //Use sorted list
        //numbers[i] = i;
    }

    if (DEBUG == 1) printf( "Unsorted list\n" );
    if (DEBUG == 1) printarray( numbers, 0, NUM_OF_INTS/2, NUM_OF_INTS );   
    if (DEBUG == 1) printf( "frontguard=%04d, backguard=%04d\n", frontguard, backguard);

    merge_sort( numbers, 0, NUM_OF_INTS );

    if (DEBUG == 1 ) printf( "\nSorted list\n"); 
    if (DEBUG == 1) printarray( numbers, 0, NUM_OF_INTS/2, NUM_OF_INTS );   
    if (DEBUG == 1) printf( "frontguard=%04d, backguard=%04d\n", frontguard, backguard);

    return 0;
}

printarray is a helper function I wrote to prettyprint what is happening in an array printarray是我编写的用于打印数组中发生的情况的辅助函数

void printarray( const int arr[], const int low, const int middle, const int high )
{
    int i;
    for (i = low; i < high; i++ )
    {
        if( i == low )
            printf( "   L%04d", i );
        else if( i == middle )
            printf( "   M%04d", i );
        else if( i == (high-1) )
            printf( "   H%04d", i );
        else 
            printf( "   *%04d", i );        
    }
    printf( "\n" );
    for( i = low; i < high; i++ )
        printf( "    %04d", arr[i] );
    printf( "\n" );
}   

It is common to have to create some helper debug functions such as this to get your code working if you do not have/want a debugger. 通常,必须创建一些辅助调试功能,例如在没有/不需要调试器的情况下才能使代码正常工作。 Do not be afraid to write some throw-away code to understand what your code is doing! 不要害怕编写一些一次性的代码来了解您的代码在做什么! In this case, I didn't need the line of L/M/H, but it is still worthwhile to spend the time. 在这种情况下,我不需要L / M / H,但是花时间还是值得的。 I recommend leaving these types of functions in your code, commented out (using a #define such as DEBUG), in case a future maintainer needs them. 我建议将这些类型的函数保留在代码中,并注释掉(使用#define,例如DEBUG),以防将来维护者需要它们。

Here is the output of your function as-is: 以下是您的函数的原样输出:

Unsorted list
   L0000   *0001   M0002   *0003   H0004
   0005    0004    0003    0002    0001
frontguard=-500, backguard=-600

Sorted list
   L0000   *0001   M0002   *0003   H0004
    -600    0001    0002    0003    0004
frontguard=-500, backguard=0005

You can see that the backguard got overwritten and "stolen" into your output. 您可以看到backguard被覆盖并“偷”到您的输出中。 (This behavior can differ on different CPU architectures, C implementations, and run specifics, btw.) The problem is that you call merge_sort from main() with high as the size of the array (5 in this case), however merge_sort expects high to be the last valid index in the array (numbers[4] is the last array item). (此行为可以在不同的CPU体系结构不同,C实现中,并运行细节,顺便说一句。)的问题是,调用merge_sortmain()high为(在此情况下5)所述阵列的尺寸,然而merge_sort期望high成为数组中的最后一个有效索引(numbers [4]是最后一个数组项)。 Modify main() to 修改main()

    merge_sort( numbers, 0, NUM_OF_INTS-1 );

and test it against a sorted, reverse sorted, and random array of numbers. 并针对排序,反向排序和随机数字数组进行测试。


Original comments: 原始评论:

Well, first off, you should be receiving a segementation fault, not just incorrectly sorted data. 好吧,首先,您应该收到一个分段错误,而不仅仅是错误地排序了数据。

  size = high - low + 1; //create a helper array and set it equal to the input array int array1[size]; for (i = low; i <= high; i++) { array1[i] = array[i]; } 

Think about what happens here when low is not zero. 想一想当低不为零时在这里会发生什么。 Let's say l=6, m=6, h=7. 假设l = 6,m = 6,h = 7。 You are setting the size of your helper array to 2, but you are accessing it with i=6, so you are trashing the stack. 您正在将辅助程序数组的大小设置为2,但是使用i = 6来访问它,因此会浪费堆栈。

The easiest fix for this is to declare int array1[high]; 最简单的解决方法是声明int array1[high]; . It's memory inefficient but it keeps the rest of the code simple, which is really more valuable. 它的内存效率低下,但它使其余代码保持简单,这实际上更有价值。

Second, your for loop is indexing past the end of array, you need to use i < high. 其次,您的for循环在数组末尾建立索引,您需要使用i <high。 In C, arrays start at 0, so an array of size 5 has valid locations at 0,1,2,3,4. 在C中,数组从0开始,因此大小为5的数组的有效位置为0、1、2、3、4。 Your code as-is would try to read from array[5] (probably not fatal), and write to array1[5] (very possibly fatal). 您的代码按原样尝试从array [5]读取(可能不是致命的),并写入array1 [5](非常可能是致命的)。 I'll bet this why you have a +1 in the size statement, since you were advancing past the end of array1 otherwise. 我敢打赌,为什么您在size语句中使用+1,否则您将前进到array1的末尾。

  for (i = low; i < high; i++) { 

These will fix your segmentation fault. 这些将解决您的细分错误。 With that fixed, you are still getting garbage data in your output. 修复此问题后,您仍将在输出中获取垃圾数据。

Your middle else-if statement is never going to be executed - any equivalent data is going to be covered by the first if statement. 您中间的else-if语句将永远不会执行-第一个if语句将覆盖所有等效数据。

Your while loop does not properly handle the degenerate cases. 您的while循环无法正确处理退化的情况。 It needs to detect if one of the two lists has been completely consumed, and if so, just copy the rest of the other list. 它需要检测两个列表之一是否已被完全消耗,如果是,则只需复制另一个列表的其余部分即可。

Also, the while loop needs separate tracker variables for low, mid, and the output array. 另外,while循环需要针对低端,中端和输出数组使用单独的跟踪器变量。 You cannot use currentLow for both low and the output array. 您不能将low和输出数组都使用currentLow。

Finally, when testing sorting, random data is not sufficient (esp. with a size of 5), you should always test the totally degenerate cases of a sorted and reverse-sorted lists. 最后,在测试排序时,随机数据是不够的(尤其是大小为5),您应该始终测试排序和反向排序列表的完全退化的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM