【问题标题】:Why is an extra element being added to my void** array when I use merge-sort?当我使用合并排序时,为什么在我的 void** 数组中添加了一个额外的元素?
【发布时间】:2019-04-08 00:08:10
【问题描述】:

当我使用mergeSort 对我的void** 数组(该数组包含指向整数的void* 指针)进行排序时,似乎向数组中添加了一个额外的1(一个新元素)。我几乎可以肯定问题出在mergeSortmerge 中,因为在调用mergeSort 之前打印我的void** 数组时,数据是正确的(只是未排序)。这是代码。

#define SIZE 10

void mergeSort(void**, int, int);
void merge(void**, int, int, int);
int compare(void*, void*);

int main(void) {
    int array[SIZE] = { 5, 6, 3, 2, 5, 6, 7, 4, 9, 3 };
    void *voidArray[SIZE];
    int query = 1;
    void *queryPointer = &query;

    for (int j = 0; j < SIZE; j++) {
        voidArray[j] = &array[j];
    }

    printArray(voidArray);
    mergeSort(voidArray, 0, SIZE);
    printArray(voidArray);
    result = binarySearch(voidArray, 0, SIZE, queryPointer);

    if (result == -1) {
        puts("Query not found.");
        return(0);
    }

    printf("Query found at index %d.\n", result);
    return(0);
}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void mergeSort(void **array, int head, int tail) {
    if (head < tail) {
        int middle = (head + ((tail - head) / 2));
        mergeSort(array, head, middle);
        mergeSort(array, (middle + 1), tail);
        merge(array, head, middle, tail);
    }
}

void merge(void **array, int head, int middle, int tail) {
    int headLength = (middle - head + 1);
    int tailLength =  (tail - middle);
    void *headSide[headLength];
    void *tailSide[tailLength];

    for (int i = 0; i < headLength; i++) {
        headSide[i] = array[head + i];
    }

    for (int j = 0; j < tailLength; j++) {
        tailSide[j] = array[middle + 1 + j];
    }

    int k = head;
    int l = 0;
    int m = 0;
    while (l < headLength && m < tailLength) {
        if (compare(headSide[l], tailSide[m]) == -1) {
            array[k] = headSide[l];
            l++;      
        } else {  
            array[k] = tailSide[m];
            m++;
        }
        k++;
    }

    while (l < headLength) {
        array[k] = headSide[l];
        l++;
        k++;
    }

    while (m < tailLength) {
        array[k] = tailSide[m];
        m++;
        k++;
    }
}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

int compare(void *index, void *query) {
    if (*((int *)index) == *((int *)query)) {
        return (0);
    }

    if (*((int*)index) > *((int*)query)) {
        return (1);        
    }

    return (-1);
}

输出应包含未排序的数组、已排序的数组以及是否找到查询。未排序的数组中没有1,但排序后的数组中有1;此外,排序结果中缺少数字 9(有趣的是,如果我对 9 执行二进制搜索,它会告诉我在索引 10 中找到了 9)。

示例输出(1 的查询):

5 6 3 2 5 6 7 4 9 3
1 2 3 3 4 5 5 6 6 7

在索引 0 中找到查询。

【问题讨论】:

  • 您需要决定是使用封闭间隔还是半开放间隔。目前你正在混合它们。
  • 就这样,你需要通过mergeSort (voidArray, 0 , SIZE-1);

标签: c mergesort void-pointers


【解决方案1】:

检查你的数组下标。

int tailLength =  (tail - middle)

tail是数组的大小,我认为tailLength不正确。

【讨论】:

  • 是的,包含 10 个元素的数组的尾部是 9,而不是我假设的 10。感谢您的帮助!
【解决方案2】:
headSide[i] = array[head + i];

headSide[i]voidarray[head + i]void*

【讨论】:

    【解决方案3】:

    margeSortmerge 的参数有些混淆。传递范围内最后一个元素的索引在C中不是惯用的。传递范围结束后元素的索引要简单得多,这与传递0SIZE int main()一致:mergeSort(voidArray, 0, SIZE);result = binarySearch(voidArray, 0, SIZE, queryPointer);

    这是使用此 API 的修改版本:

    void mergeSort(void **array, int head, int tail) {
        if (tail - head > 1) {
            int middle = head + (tail - head) / 2);
            mergeSort(array, head, middle);
            mergeSort(array, middle, tail);
            merge(array, head, middle, tail);
        }
    }
    
    void merge(void **array, int head, int middle, int tail) {
        int headLength = middle - head;
        int tailLength = tail - middle;
        void *headSide[headLength];
        void *tailSide[tailLength];
    
        for (int i = 0; i < headLength; i++) {
            headSide[i] = array[head + i];
        }
        for (int j = 0; j < tailLength; j++) {
            tailSide[j] = array[middle + j];
        }
    
        int k = head;
        int l = 0;
        int m = 0;
        while (l < headLength && m < tailLength) {
            if (compare(headSide[l], tailSide[m]) <= 0) {
                array[k++] = headSide[l++];
            } else {  
                array[k++] = tailSide[m++];
            }
        }
        while (l < headLength) {
            array[k++] = headSide[l++];
        }
        while (m < tailLength) {
            array[k++] = tailSide[m++];
        }
    }
    

    但是请注意,使用自动存储(又名在堆栈上)分配临时数组 headSidetailSide 对于大型数组是有风险的。此外,没有必要将右半部分的元素保存到tailSide,因为它们在复制到最终位置之前不会被覆盖。这是merge的更简单版本:

    void merge(void **array, int head, int middle, int tail) {
        int headLength = middle - head;
        void *headSide[headLength];
    
        for (int i = 0; i < headLength; i++) {
            headSide[i] = array[head + i];
        }
    
        int k = head;
        int l = 0;
        while (l < headLength && middle < tail) {
            if (compare(headSide[l], array[middle]) <= 0) {
                array[k++] = headSide[l++];
            } else {  
                array[k++] = array[middle++];
            }
        }
        while (l < headLength) {
            array[k++] = headSide[l++];
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-24
      • 2020-12-07
      相关资源
      最近更新 更多